阅读:1683回复:9
Execuive and Suspended
我在Water Oney 的《Programming Windows Driver Model》书中看到递交一个URB 等待完成时,使用
KeWaitForSingleObjec(&event,Executive,KernelMode,FALSE,NULL) 而在其他书中讲到,应该使用 KeWaitForSingleObjec(&event,Suspended,KernelMode,FALSE,NULL) 那么Executive 和 Suspended 哪个正确呢? |
|
沙发#
发布于: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 |
|
|
板凳#
发布于: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. |
|
|
地板#
发布于: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) 到底什么原因,有差别吗? |
|
地下室#
发布于: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 |
|
|
5楼#
发布于:2002-06-12 16:16
老大,超时问题怎么做啊?
|
|
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的返回值进行相应的处理。 |
|
|
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 的方法,但在实际中去出现蓝屏的现象! 版主,上面的代码能实现吗? |
|
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。 |
|
|
9楼#
发布于:2002-06-13 13:33
而且完成例程一般运行于arbitrary thread context,所以这里用TRUE不安全。
|
|
|