设备描述符请求失败_Windows PnP设备驱动删除设备的处理流程

参考文档:Understanding When Remove IRPs Are Issued - Windows drivers

Windows对于PnP(即插即用)设备,有一个专门的IRP Major Code定义:IRP_MJ_PNP,任何PnP设备驱动以及工作在PnP设备协议栈之上的驱动(如文件系统驱动)和过滤驱动都需要处理IRP_MJ_PNP请求,尤其是删除的过程,如果驱动没有针对这类请求进行处理,可能会导致系统挂起或者删除设备失败。一个常见的用户层面表现就是无法安全弹出U盘。

本文主要翻译自前面的链接,不保证内容一定正确(未进行完整验证)。

PnP设备有两种删除流程,一种是正常删除,也就是用户层面发起的“安全弹出”请求;另一种是用户直接拔出设备,这种是非正常删除。

对于正常安全删除的流程:

Windows会先发起一个IRP_MN_QUERY_REMOVE_DEVICE请求,去查询设备是否可以正常删除,如果此时设备忙,则可以通过Irp->IoStatus.Status返回一个STATUS_UNSUCCESSFUL,同时调用IoCompleteRequest,并且不传播Irp给下层驱动。这样在用户层面上,就会提示设备忙,无法删除。

如果驱动认为设备时可以删除的,那么收到此请求以后,就应该禁止新的其它请求进入,同时设置Irp->IoStatus.Status为STATUS_SUCCESS,并调用IoSkipCurrentIrpStackLocation和IoCallDriver传播这个Irp到更底层的设备。

通常来说,如果这个请求返回成功,那么驱动此时就应该释放一些资源,当然驱动也可以选择不释放,而是仅仅阻止更多的请求进入,具体驱动选择哪种行为,由驱动自己决定,但通常情况下,对设备加锁是必需的,也要阻止任何“创建”类型的请求进入驱动。

当IRP_MN_QUERY_REMOVE_DEVICE返回成功,并且整个设备栈上的所有驱动都返回成功时,Windows的PnP管理器会发送IRP_MN_REMOVE_DEVICE请求,完成对设备彻底删除,当收到IRP_MN_REMOVE_DEVICE请求时,驱动需要释放全部资源,关闭设备,停止还在执行中的其它Irp请求。同时,驱动也要传播这个请求到下层驱动。

Windows文档中要求:IRP_MN_REMOVE_DEVICE请求是必须成功的,不能失败,否则可能会造成设备状态信息不一致。

IRP_MN_REMOVE_DEVICE请求有可能是驱动被卸载前的最后一个请求,所以必须要保证所有资源被正确释放。

如果IRP_MN_QUERY_REMOVE_DEVICE返回失败,那么Windows会重新发送一个IRP_MN_CANCEL_REMOVE_DEVICE请求通知驱动以及整个设备栈取消之前的请求。

当驱动收到IRP_MN_CANCEL_REMOVE_DEVICE时,需要解开设备锁定的状态,并允许“创建”类型的请求进入驱动。类似地,IRP_MN_CANCEL_REMOVE_DEVICE也要被传播到底层驱动,通知底层设备驱动更新状态。

还有一种特例是,虽然IRP_MN_QUERY_REMOVE_DEVICE返回成功,但上层代码改变主意,不希望删除设备,那么也会发送一个IRP_MN_CANCEL_REMOVE_DEVICE请求,对于这个请求的处理跟前面描述的是一致的:更新状态,传播Irp到底层。

所以大致的流程图如下

IRP_MN_QUERY_REMOVE_DEVICE(查询是否可以删除)
|
+-----(失败)---> IRP_MN_CANCEL_REMOVE_DEVICE
|
+-----(用户层面取消请求)---> IRP_MN_CANCEL_REMOVE_DEVICE
|
(成功)
v
IRP_MN_REMOVE_DEVICE (可能是最后一个IRP)

对于非正常拔出设备的删除流程:

Windows PnP管理器会发送一个IRP_MN_SURPRISE_REMOVAL请求给驱动,通知驱动这个设备已经被强制删除了。

这个时候驱动需要做的事情如下:

1. 检查设备是否还存在,如果还存在,需要停止并删除设备(笔者注:这段状态很奇怪,但文档里是这么写的)
2. 释放全部资源,阻止新的IO请求。
3. 除了IRP_MJ_CLEANUP,IRP_MJ_CLOSE,IRP_MJ_POWER,IRP_MJ_PNP之外,其它IRP都需要被阻止。
4. 如果过滤驱动不能处理这个请求,向底层传播。
5. 设置Irp->IoStatus.Status为STATUS_SUCCESS,必须成功,不能失败。
6. 调用IoSkipCurrentIrpStackLocation和IoCallDriver传播IRP
7. 通过IoCallDriver获得返回值并返回IRP dispatch函数
8. 不要调用任何Complete函数

当IRP_MN_SURPRISE_REMOVAL请求返回以后,Windows会继续发送一个IRP_MN_REMOVE_DEVICE完成设备删除,流程与正常安全移除设备的方式一致。

BTW:我一个VxWorks码农,为啥要写Windows驱动呢?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值