阅读:1785回复:6
请教:未完成IRP如何处理
问题是这样:
驱动程序向设备发送读数据指令,由于某种原因设备没有反映。这样用户程序就一直处于等待中。我现在的想法是:在驱动中加入定时器,如果读数据指令在500ms没反映,驱动程序认为该IRP处理错误。这样用户程序就不用一直等待。那么如何处理这个未完成的IRP? |
|
沙发#
发布于:2007-06-27 21:49
IoCompleteIRP完成就是了,或则先不完成,到时候由用户程序调用CancelIRP来Cancel
|
|
板凳#
发布于:2007-06-28 23:30
我是这样做的,不知道合适否?
首先在定时器的回调历程中调用IoCancelIrp,取消这个Irp。这时IoManager会调用这个Irp的完成历程,在完成历程中释放分配的内存。然后在读写命令ID中调用IoCompleteIrp。从效果来看,达到了目的。 但是不能在定时器回调历程中调用IoCompleteIrp,这样做就蓝屏。 还有一种取消IRP的方法,用新的IRP队列代替原来的IRP队列,新的没有要取消的IRP。这种方法我还不太理解 |
|
地板#
发布于:2007-06-29 08:41
没必要这么麻烦。
拿到IRP的时候返回STATUS_PENDING,然后在timer callback中根据读取的结果返回对应的status |
|
|
地下室#
发布于:2007-06-29 13:57
一般就是像三楼说的
KeInitializeEvent(&event, NotificationEvent, FALSE); irp = IoBuildDeviceIoControlRequest( IOCTL_INTERNAL_USB_SUBMIT_URB, pdx->LowerDeviceObject, NULL, 0, NULL, 0, TRUE, &event, &ioStatus); nextStack = IoGetNextIrpStackLocation(irp); nextStack->Parameters.Others.Argument1 = Urb; ntStatus = IoCallDriver(pdx->LowerDeviceObject,irp); if (ntStatus == STATUS_PENDING) { //If pending wait until Time out occurs //KeWaitForSingleObject(&event,Suspended,KernelMode,FALSE,NULL); TimeoutPeriod.QuadPart = -10000 * 5000; ntStatus = KeWaitForSingleObject(&event, Executive, KernelMode, 0, &TimeoutPeriod ); if (STATUS_TIMEOUT == ntStatus) { NTSTATUS ntStatus2; DbgLogInfo(("UsbCallUSBDI timed out.\n")); // myDbgPrint(("CUsbInterface::UsbCall_GSPN(): %d has timed out.\n", // FuncID // )); if (IoCancelIrp(irp)) { ntStatus2 = KeWaitForSingleObject(&event, Executive, KernelMode, 0, &TimeoutPeriod ); if (STATUS_TIMEOUT == ntStatus2) { DbgLogInfo(("Cancelled the IRP but completion routine didn't get called\n")); // myDbgPrint(("CUsbInterface::UsbCall_GSPN() Strange behaviour : Cancelled the IRP but completion routine didn't get called\n")); } else { DbgLogInfo(("CUsbInterface::UsbCall_GSPN() Cancelled the IRP, completion routine got called : looks ok\n")); // myDbgPrint(("CUsbInterface::UsbCall_GSPN() Cancelled the IRP, completion routine got called : looks ok\n")); } } else { DbgLogInfo(("CUsbInterface::UsbCall_GSPN() IoCancelIrp Failed\n")); // myDbgPrint(("CUsbInterface::UsbCall_GSPN() IoCancelIrp Failed\n")); } ntStatus = STATUS_IO_TIMEOUT; } else { //ntStatus = pIrp->IoStatus.Status; ntStatus=ioStatus.Status; } |
|
5楼#
发布于:2007-06-29 14:06
不过这种处理虽然简单,但是在某些USB控制器的高速传输中会有造成速度损失,因为不能让USB进行饱和传输(在一个USB周期内插入尽量多的块)。如果要实现高速传输应该同时发若干个IRP请求,保证在处理某个IRP超时的时候还有其他IRP在PENDING着数据,以达到最高的效率,象读取视频流的AVStream就需要这样实现的而且还用配合buffer的PENDING
|
|
6楼#
发布于:2007-07-01 00:54
谢谢楼上兄弟了,我试一试。
|
|