shlei20
驱动牛犊
驱动牛犊
  • 注册日期2002-02-01
  • 最后登录2003-02-08
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1683回复:9

Execuive and Suspended

楼主#
更多 发布于:2002-06-12 11:02
我在Water Oney 的《Programming Windows Driver Model》书中看到递交一个URB 等待完成时,使用
KeWaitForSingleObjec(&event,Executive,KernelMode,FALSE,NULL)

而在其他书中讲到,应该使用
KeWaitForSingleObjec(&event,Suspended,KernelMode,FALSE,NULL)



那么Executive 和 Suspended 哪个正确呢?
Tom_lyd
驱动大牛
驱动大牛
  • 注册日期2001-09-02
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2002-06-12 11:16
DDK文档中如下解释道:
Specifies the reason for the wait. A driver should set this value to Executive, unless it is doing work on behalf of a user and is running in the context of a user thread, in which case it should set this value to UserRequest.
你的这种情况应该用Executive
Tom_lyd
Tom_lyd
驱动大牛
驱动大牛
  • 注册日期2001-09-02
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2002-06-12 11:16
DDK文档中如下解释道:
Specifies the reason for the wait. A driver should set this value to Executive, unless it is doing work on behalf of a user and is running in the context of a user thread, in which case it should set this value to UserRequest.
你的这种情况应该用Executive.
Tom_lyd
shlei20
驱动牛犊
驱动牛犊
  • 注册日期2002-02-01
  • 最后登录2003-02-08
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2002-06-12 14:20
我在Water Oney 的《Programming Windows Driver Model》书中看到递交一个URB 等待完成时,使用
KeWaitForSingleObjec(&event,Executive,KernelMode,FALSE,NULL)


Chris Cant 强调用
KeWaitForSingleObjec(&event,Suspended,KernelMode,FALSE,NULL)


到底什么原因,有差别吗?
Tom_lyd
驱动大牛
驱动大牛
  • 注册日期2001-09-02
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2002-06-12 15:10
DDK中的解释已经够清楚了,一般来说,都是用Executive,用Suspended的场合有很多限制,诸如,一定要保证在用户线程的上下文环境中。这样,在完成例程中、Worker Thread中一定不能用Suspended,在Dispatch例程可以用Suspended.
该参数是一个enum变量,定义如下:
//
// Wait reasons
//

typedef enum _KWAIT_REASON {
    Executive,
    FreePage,
    PageIn,
    PoolAllocation,
    DelayExecution,
    Suspended,
    UserRequest,
    WrExecutive,
    WrFreePage,
    WrPageIn,
    WrPoolAllocation,
    WrDelayExecution,
    WrSuspended,
    WrUserRequest,
    WrEventPair,
    WrQueue,
    WrLpcReceive,
    WrLpcReply,
    WrVirtualMemory,
    WrPageOut,
    WrRendezvous,
    Spare2,
    Spare3,
    Spare4,
    Spare5,
    Spare6,
    WrKernel,
    MaximumWaitReason
    } KWAIT_REASON;
具体指的是被等待对象需要等待的原因。

大多数情况下,在驱动程序下都是用Executive
Tom_lyd
shlei20
驱动牛犊
驱动牛犊
  • 注册日期2002-02-01
  • 最后登录2003-02-08
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2002-06-12 16:16
老大,超时问题怎么做啊?
Tom_lyd
驱动大牛
驱动大牛
  • 注册日期2001-09-02
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2002-06-12 17:47
在内核中处理超时,用下面的方法:
定义一个LARGE_INTEGER型超时变量
NT_STATUS status;
LARGE_INTEGER timeout;
timeout.QuadPart = -5*10000000; //负数表示相对时间,此为5秒
status = KeWaitForSingleObject( pWaitObject, Executive,
KernelMode,
FALSE,
&timeout );
然后可以根据KeWaitForSingleObject的返回值进行相应的处理。
Tom_lyd
shlei20
驱动牛犊
驱动牛犊
  • 注册日期2002-02-01
  • 最后登录2003-02-08
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2002-06-13 08:58
请看下面的代码:

//***********************************************************************
//function:Evk_CallUSBD
//parameter: fdo ----- next lower function device object
// urb ----- usb request block,already formatted
//purpose: the following one routine is to forward a urb to usb bus driver
// The client device driver passes USB request block (URB) structures
// to the class driver as a parameter in an IRP with Irp->MajorFunction
// set to IRP_MJ_INTERNAL_DEVICE_CONTROL and the next IRP stack location
// Parameters.DeviceIoControl.IoControlCode field set to
// IOCTL_INTERNAL_USB_SUBMIT_URB.
//
//return: if the operation is successful,return STATUS_SUCCESS
//
//revision: date,2002,6,10. by shenlei
// purpose: 增加超时的处理: 超时情况是经常出现的,主要源于
// 设备端对主机提出的要求没有响应。当设备由于不可预料原因 没有响应 时,
// 就无法正常处理
//
// Note that we create our own IRP here and use it to send the request to
// the USB software subsystem. This means that this routine is essentially
// independent of the IRP that caused this driver to be called in the first
// place. The IRP for this transfer is created, used, and then destroyed
// in this routine.

//********************************************************************
NTSTATUS
Evk_CallUSBD(IN PDEVICE_OBJECT fdo,
IN PURB urb)
{
NTSTATUS ntStatus,status=STATUS_SUCCESS;
PDEVICE_EXTENSION pdx;


PIRP irp;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION nextStack;

KEVENT event;

Evk_KdPrint((\"enter Evk_CallUSBD()\\n\"));

pdx=fdo->DeviceExtension;

//issue a synchronous request(同步请求)
KeInitializeEvent(&event,NotificationEvent,FALSE);

//build irp which will be send to bus driver
irp=IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB,
pdx->LowerDeviceObject,
NULL,
0,
NULL,
0,
TRUE, //internal
&event,
&ioStatus);
//newly added for timeout
IoSetCompletionRoutine(irp,
(PIO_COMPLETION_ROUTINE)HUSBDCompletionRoutine,
(PVOID)&event,
TRUE,
TRUE,
TRUE);

//prepare for calling the usb bus driver
nextStack=IoGetNextIrpStackLocation(irp);
ASSERT(nextStack!=NULL);

nextStack->Parameters.Others.Argument1=urb;

Evk_KdPrint((\"Calling USB driver stack\"));

//call the USB driver stack to perform the operation.if the return value is
//PENDING ,wait for request to complete

ntStatus=IoCallDriver(pdx->LowerDeviceObject,irp);

Evk_KdPrint ((\"return from IoCallDriver USBD %x\\n\", ntStatus));

//STATUS_PENDING means the lower driver have not finished processing the IRP,
//yet.we must wait.
if(ntStatus==STATUS_PENDING)
{
LARGE_INTEGER timeout5second;

timeout5second.QuadPart=-5*10000000; //5秒

Evk_KdPrint ((\"Wait for single object\\n\"));

status=KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
&timeout5second);
if(status==STATUS_TIMEOUT)
{
IoCancelIrp(irp);
KeWaitForSingleObject(&event,Suspended,KernelMode,FALSE,NULL);
}

Evk_KdPrint ((\"Wait for single object, returned %x\\n\", status));


}
else
{
ioStatus.Status=ntStatus;

//added here
KeClearEvent(&event);
IoCompleteRequest(irp,IO_NO_INCREMENT);
KeWaitForSingleObject(&event,Suspended,KernelMode,FALSE,NULL);
}

Evk_KdPrint ((\"URB status = %x status = %x irp status %x\\n\",
urb->UrbHeader.Status, status, ioStatus.Status));


//USBD maps the error code for us,USBD uses error codes in its URB structure,
//that are more insightful into USB behavior.in order to match the
//NT status code,USBD maps its error codes into more general NT
// error categories so higher level drivers can decipher the error codes
// based on standard NT error code definitions.
//

ntStatus=ioStatus.Status;
//
// If the URB status was not USBD_STATUS_SUCCESS, we save a copy of the
// URB status in the device extension. After a failure, another IOCTL,
// IOCTL_EVK_GET_LAST_ERROR can be used to retrieve the URB status
// for the most recently failed URB. Of course, this status gets
// overwritten by subsequent failures, but it\'s better than nothing.
//
if(NT_SUCCESS(ntStatus))
{
if(!USBD_SUCCESS(urb->UrbHeader.Status))
ntStatus=STATUS_UNSUCCESSFUL;
}

Evk_KdPrint((\"exit Evk_CallUSBD (%x)\\n\", ntStatus));
return ntStatus;
}

//**************************************************************************
//function : HUSBDCompletionRoutine
//parameter:
//**************************************************************************
NTSTATUS
HUSBDCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
PKEVENT pEvent = (PKEVENT)Context;
KeSetEvent(pEvent, 0, TRUE);
return STATUS_MORE_PROCESSING_REQUIRED;
}


有没有人在USB中处理过超时的问题? 我觉得有必要啊,但不知怎么办? 上面的代码基本上是Walter Oney 的方法,但在实际中去出现蓝屏的现象!

版主,上面的代码能实现吗?
Tom_lyd
驱动大牛
驱动大牛
  • 注册日期2001-09-02
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2002-06-13 13:31
//**************************************************************************
//function : HUSBDCompletionRoutine
//parameter:
//**************************************************************************
NTSTATUS
HUSBDCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
PKEVENT pEvent = (PKEVENT)Context;
KeSetEvent(pEvent, 0, TRUE);
return STATUS_MORE_PROCESSING_REQUIRED;
}

你的完成例程好象有问题,DDK文档中有这样的一个解释:
If Wait is set to FALSE, the caller can be running at IRQL <= DISPATCH_LEVEL. Otherwise, callers of KeSetEvent must be running at IRQL PASSIVE_LEVEL and in a nonarbitrary thread context.
完成例程的运行IRQL很有可能在DISPATCH_LEVEL,而你在这里指定bWait为TRUE,极易造成蓝屏,试试FALSE。




Tom_lyd
Tom_lyd
驱动大牛
驱动大牛
  • 注册日期2001-09-02
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2002-06-13 13:33
而且完成例程一般运行于arbitrary thread context,所以这里用TRUE不安全。
Tom_lyd
游客

返回顶部