USB通用驱动源码分析
+ -

Windows驱动设备移除与竞争问题

2025-06-13 0 0

对于设备的IPR回调处理函数中,对于IRP_MN_REMOVE_DEVICE请求做引用计数

  if (!((majorFunction == IRP_MJ_PNP) && (minorFunction == IRP_MN_REMOVE_DEVICE))){
        IncrementPendingActionCount(parentFdoExt);
    }

这样在其设备移除IRP_MN_REMOVE_DEVICE时进行

        /*
         *  Do an extra decrement on the pendingActionCount.
         *  This will cause the count to eventually go to -1
         *  (once all IO completes),
         *  at which time we'll continue.
         */
        DecrementPendingActionCount(parentFdoExt);

        KeWaitForSingleObject( &parentFdoExt->removeEvent,
                               Executive,
                               KernelMode,
                               FALSE,
                               NULL );

其中DecrementPendingActionCount为负数时,表示所有IRP已经完成,置事件完成后的IRP_MN_REMOVE_DEVICE

VOID DecrementPendingActionCount(PPARENT_FDO_EXT parentFdoExt)
{
    ASSERT(parentFdoExt->pendingActionCount >= 0);
    InterlockedDecrement(&parentFdoExt->pendingActionCount);    
    if (parentFdoExt->pendingActionCount < 0){
        /*
         *  All pending actions have completed and we've gotten
         *  the REMOVE_DEVICE IRP.
         *  Set the removeEvent so we'll stop waiting on REMOVE_DEVICE.
         */
        ASSERT((parentFdoExt->state == STATE_REMOVING) || (parentFdoExt->state == STATE_REMOVED));
        KeSetEvent(&parentFdoExt->removeEvent, 0, FALSE);
    }
}

这段代码和注释解释了一种在 Windows 驱动程序开发中处理 IRP(I/O Request Packet,输入/输出请求包)时的同步机制,特别是针对 PnP(即插即用)设备移除操作(IRP_MN_REMOVE_DEVICE)的竞态条件防护。

代码功能解析:

  1. 条件判断

    • if (!((majorFunction == IRP_MJ_PNP) && (minorFunction == IRP_MN_REMOVE_DEVICE)))
      这个条件检查当前 IRP 不是 PnP 的 REMOVE_DEVICE 请求。如果是其他类型的 IRP(如读、写、查询等),或者虽然是 PnP IRP 但不是移除设备操作,则进入分支。
  2. PendingActionCount 的作用

    • IncrementPendingActionCount(parentFdoExt)
      对设备扩展(parentFdoExt)中的 PendingActionCount 计数器进行递增
      这个计数器用于跟踪当前正在处理的、尚未完成的非移除设备操作(如读写、配置等)的数量。

注释解释的竞态条件问题:

  1. 问题场景

    • 假设一个线程正在处理普通 IRP(如读写操作),此时突然收到 REMOVE_DEVICE 请求(设备移除)。
    • 如果没有 PendingActionCount 的保护,REMOVE_DEVICE 可能会直接释放设备对象(Device Object)和设备扩展(Device Extension)的内存。
    • 但此时另一个线程仍在执行读写操作,访问已释放的内存,导致崩溃或数据损坏
  2. 解决方案

    • 对于所有非移除设备的 IRP,提前递增 PendingActionCount,表示“有一个操作正在使用设备”。
    • REMOVE_DEVICE 请求到达时,必须等待 PendingActionCount 降为 0(即所有操作完成)才能继续移除设备。
    • 这确保了设备对象和扩展在不再被使用时才被释放。

关键点总结:

  • 同步机制PendingActionCount 是一个引用计数器,用于防止设备在仍有操作未完成时被意外移除。
  • 移除操作的特殊性REMOVE_DEVICE 是唯一不需要递增此计数器的操作,因为它的执行需要依赖其他操作完成后才能继续。
  • PnP 设备管理:这是 Windows 驱动模型中即插即用功能的核心安全措施之一。

这种模式在驱动程序开发中非常常见,尤其是在处理动态设备插拔和资源释放时。

HID人机交互QQ群:564808376    UAC音频QQ群:218581009    UVC相机QQ群:331552032    BOT&UASP大容量存储QQ群:258159197    STC-USB单片机QQ群:315457461    USB技术交流QQ群2:580684376    USB技术交流QQ群:952873936   

0 篇笔记 写笔记

关注公众号
  • HID人机交互
  • Linux&USB
  • UAC音频
  • TYPE-C
  • USB规范
  • USB大容量存储
  • USB百科
  • USB周边
  • UVC摄像头
  • Windows系统USB
  • 音视频博客
  • 取消
    感谢您的支持,我会继续努力的!
    扫码支持
    扫码打赏,你说多少就多少

    打开支付宝扫一扫,即可进行扫码打赏哦

    您的支持,是我们前进的动力!