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

问一个分层驱动的IRP发送问题。

楼主#
更多 发布于:2004-05-27 11:25
我写的分层驱动,上层驱动用用IoRegisterPlugPlayNotification()监听USB设备的插拔,然后用IoGetDeviceObjectPointer()取得其deviceObject,然后IoBuildDeviceIoControlRequest()构造IRP让他们通信。
现在问题是,如果上层驱动将IRP发给下层,而在等待下层驱动返回IRP的过程中,下层设备被拔掉,会造成死机。请问这个问题如何处理, 请有经验的大侠指教。
程序结构如下:

KeInitializeEvent(&kevent, SynchronizationEvent, false);
        
pIrp = IoBuildDeviceIoControlRequest();
if(pIrp == NULL)
{
         return STATUS_INSUFFICIENT_RESOURCES;
}
                          
        
status = IoCallDriver(DeviceObject, pIrp);
if (status == STATUS_PENDING)
{
        KeWaitForSingleObject( &kevent, Executive, KernelMode, FALSE, NULL );
     status = IoStatus.Status;
}

我想知道,如果在KeWaitForSingleObject()中,下层设备拔掉,造成死机怎么处理,谢谢!
seaquester
驱动大牛
驱动大牛
  • 注册日期2002-05-22
  • 最后登录2016-06-16
  • 粉丝0
  • 关注0
  • 积分500分
  • 威望115点
  • 贡献值0点
  • 好评度107点
  • 原创分0分
  • 专家分52分
沙发#
发布于:2004-05-27 11:32
可能是下层驱动没有结束你的请求,应该在你的下层驱动的CleanUp例程(IRP_MJ_CLEANUP)中结束所有IRP。
八风舞遥翩,九野弄清音。 鸣高常向月,善舞不迎人。
sinking
驱动牛犊
驱动牛犊
  • 注册日期2003-08-18
  • 最后登录2006-02-06
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-05-27 15:50
谢谢你的回复,能具体讲讲吗?我的下层驱动是在DDk带的BulkUsb基础上改的,里面没有用IRP_MJ_CLEANUP,而是在IRP_MN_SURPRISE_REMOVAL和IRP_MN_REMOVE_DEVICE中cancel了IRP。IRP_MJ_CLEANUP是PnP管理器自动发送给驱动的吗?
sinking
驱动牛犊
驱动牛犊
  • 注册日期2003-08-18
  • 最后登录2006-02-06
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-05-28 17:26
请大侠指教,我写了个IRP_MJ_CLEANUP的处理函数,但是怎么觉得突然拔出后,没有调用它啊。另外,我在IRP_MN_SURPRISE_REMOVAL和IRP_MN_REMOVE_DEVICE中用IoCancelIrp()直接cancel掉了上层驱动发过来,但还没有完成的IRP。但仍然会产生DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS的错误,请大侠们指点一下了。
xiaorain
驱动牛犊
驱动牛犊
  • 注册日期2003-04-21
  • 最后登录2005-11-05
  • 粉丝0
  • 关注0
  • 积分7分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2004-06-02 11:14
是否应该先判断是否可以cancel,然后在进一步处理。
cancel不行的话,可以直接iocompleterequest吧。
另:你没有添加完成历程,那没你的kewaitforsingleobject(0
什么时候才会满足呢?
sinking
驱动牛犊
驱动牛犊
  • 注册日期2003-08-18
  • 最后登录2006-02-06
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-06-03 16:45
能讲讲什么时候可以cancel,什么时候要完成啊,不是很明白。我在kewaitforsingleobject()中设了等待时间,超时就返回STATUS_TIMEOUT
Shentu
驱动小牛
驱动小牛
  • 注册日期2004-04-05
  • 最后登录2011-01-24
  • 粉丝0
  • 关注0
  • 积分234分
  • 威望24点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2004-06-04 08:53
我的理解是这样的,当你下层正在处理这个 Irp 时,我们就不能够 cancel它,而如果这个Irp在队列里的话呢,可以直接cancel掉。
这些动作都应该在下层完成。
上层在构造Irp的时候,要设置一个完成例程。


[编辑 -  6/4/04 by  Shentu]
acidfish
驱动小牛
驱动小牛
  • 注册日期2002-05-20
  • 最后登录2009-11-11
  • 粉丝0
  • 关注0
  • 积分21分
  • 威望3点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2004-06-04 17:22
请大侠指教,我写了个IRP_MJ_CLEANUP的处理函数,但是怎么觉得突然拔出后,没有调用它啊。另外,我在IRP_MN_SURPRISE_REMOVAL和IRP_MN_REMOVE_DEVICE中用IoCancelIrp()直接cancel掉了上层驱动发过来,但还没有完成的IRP。但仍然会产生DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS的错误,请大侠们指点一下了。


如果设备突然拔出,pnp mgr会发送surprise_removal,然后发送remove_device。此后如果你的driver还有app CreateFile以后没有CloseHandle的话,直到你的app调用CloseHandle的时候,才会调用你的Cleanup和Close。所以USB驱动要做好这一点的操作。
还有一点:IoCancelIrp只能由最高层的发送IoCallDriver的driver层可以调用。其他层调用不知道会产生什么效果,我没有试过。
xiaorain
驱动牛犊
驱动牛犊
  • 注册日期2003-04-21
  • 最后登录2005-11-05
  • 粉丝0
  • 关注0
  • 积分7分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2004-06-05 11:24
应该可以不用设置完成例程,event对象对于自己创建的irp可以在下层驱动调用completerequest的时候设置,不过如果下层没有执行complete的时候,可能就需要完成例程了了。
bingjie
驱动小牛
驱动小牛
  • 注册日期2001-08-15
  • 最后登录2007-11-29
  • 粉丝0
  • 关注0
  • 积分36分
  • 威望5点
  • 贡献值0点
  • 好评度3点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2004-06-07 13:44
在你的底层驱动里的入口函数里做个同步就可以了。进入DispatchIoControl后先申请RemoveLock锁,这样在SupriseRemove时等待DispatchIoControl执行结束后再执行卸载动作。另外还可做一个引用计数,当发现在设备被拔出时还有人访问你的驱动时,不释放DeviceObject对象,只是标记设备被删除,此时所有的DeviceIoControl都返回失败,直到调用者调用了你的DispatchClose函数后再释放DeviceObject对象。
游客

返回顶部