IoManager
驱动牛犊
驱动牛犊
  • 注册日期2007-05-04
  • 最后登录2008-12-29
  • 粉丝1
  • 关注1
  • 积分185分
  • 威望35点
  • 贡献值0点
  • 好评度30点
  • 原创分0分
  • 专家分0分
阅读:1785回复:6

请教:未完成IRP如何处理

楼主#
更多 发布于:2007-06-27 13:34
问题是这样:
           驱动程序向设备发送读数据指令,由于某种原因设备没有反映。这样用户程序就一直处于等待中。我现在的想法是:在驱动中加入定时器,如果读数据指令在500ms没反映,驱动程序认为该IRP处理错误。这样用户程序就不用一直等待。那么如何处理这个未完成的IRP?
treedi
驱动牛犊
驱动牛犊
  • 注册日期2001-07-13
  • 最后登录2018-05-28
  • 粉丝0
  • 关注0
  • 积分181分
  • 威望28点
  • 贡献值0点
  • 好评度18点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2007-06-27 21:49
IoCompleteIRP完成就是了,或则先不完成,到时候由用户程序调用CancelIRP来Cancel
IoManager
驱动牛犊
驱动牛犊
  • 注册日期2007-05-04
  • 最后登录2008-12-29
  • 粉丝1
  • 关注1
  • 积分185分
  • 威望35点
  • 贡献值0点
  • 好评度30点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2007-06-28 23:30
我是这样做的,不知道合适否?
  首先在定时器的回调历程中调用IoCancelIrp,取消这个Irp。这时IoManager会调用这个Irp的完成历程,在完成历程中释放分配的内存。然后在读写命令ID中调用IoCompleteIrp。从效果来看,达到了目的。
  但是不能在定时器回调历程中调用IoCompleteIrp,这样做就蓝屏。
  还有一种取消IRP的方法,用新的IRP队列代替原来的IRP队列,新的没有要取消的IRP。这种方法我还不太理解
rayyang2000
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2012-09-13
  • 粉丝3
  • 关注0
  • 积分1036分
  • 威望925点
  • 贡献值3点
  • 好评度823点
  • 原创分0分
  • 专家分0分
地板#
发布于:2007-06-29 08:41
没必要这么麻烦。

拿到IRP的时候返回STATUS_PENDING,然后在timer callback中根据读取的结果返回对应的status
天天coding-debugging中----超稀饭memory dump file ======================================================== [b]Windows Device Driver Development and Consulting Service[/b] [color=blue][url]http://www.ybwork.com[/url][/color] ========================================================
tkcat
驱动牛犊
驱动牛犊
  • 注册日期2003-07-21
  • 最后登录2007-06-29
  • 粉丝0
  • 关注0
  • 积分124分
  • 威望13点
  • 贡献值0点
  • 好评度12点
  • 原创分0分
  • 专家分0分
地下室#
发布于: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;
        }
tkcat
驱动牛犊
驱动牛犊
  • 注册日期2003-07-21
  • 最后登录2007-06-29
  • 粉丝0
  • 关注0
  • 积分124分
  • 威望13点
  • 贡献值0点
  • 好评度12点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2007-06-29 14:06
不过这种处理虽然简单,但是在某些USB控制器的高速传输中会有造成速度损失,因为不能让USB进行饱和传输(在一个USB周期内插入尽量多的块)。如果要实现高速传输应该同时发若干个IRP请求,保证在处理某个IRP超时的时候还有其他IRP在PENDING着数据,以达到最高的效率,象读取视频流的AVStream就需要这样实现的而且还用配合buffer的PENDING
IoManager
驱动牛犊
驱动牛犊
  • 注册日期2007-05-04
  • 最后登录2008-12-29
  • 粉丝1
  • 关注1
  • 积分185分
  • 威望35点
  • 贡献值0点
  • 好评度30点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2007-07-01 00:54
谢谢楼上兄弟了,我试一试。
游客

返回顶部