使用删除锁

删除锁例程提供了一种方法来跟踪设备上未完成的 I/O 操作数,并确定何时可以安全分离和删除驱动程序的设备对象。 系统向驱动程序编写者提供这些例程,作为实现其自己的跟踪机制的替代方法。

驱动程序可以将此机制用于两个目的:

  1. 若要确保驱动程序的 DispatchPnP 例程不会完成 IRP_MN_REMOVE_DEVICE (锁定时,另一个驱动程序例程) 访问设备。

  2. 计算驱动程序不应删除其设备对象的原因数,并在该计数为零时设置事件。

若要初始化删除锁,驱动程序应在其设备扩展中分配IO_REMOVE_LOCK结构,然后调用 IoInitializeRemoveLock。 当驱动程序初始化设备对象的设备扩展的其余部分时,驱动程序通常会在其 AddDevice 例程中调用 IoInitializeRemoveLock

驱动程序必须在每次启动 I/O 操作时调用 IoAcquireRemoveLock 。 每次完成 I/O 操作时,驱动程序都必须调用 IoReleaseRemoveLock 。 驱动程序可以多次获取锁。 remove lock 例程维护锁的未完成购置的计数。 每次调用 IoAcquireRemoveLock 都会递增计数, 而 IoReleaseRemoveLock 会递减计数。

驱动程序还应在将对计时器、DPC、回调等) 的代码 (的引用传出时调用 IoAcquireRemoveLock 。 然后,当事件返回时,驱动程序必须调用 IoReleaseRemoveLock

在其 用于IRP_MN_REMOVE_DEVICE的调度代码中,驱动程序必须再次获取锁,然后调用 IoReleaseRemoveLockAndWait。 在释放锁的所有未完成购置之前,此例程不会返回。 若要允许完成排队的 I/O 操作,每个驱动程序应在将IRP_MN_REMOVE_DEVICE请求传递给下一个较低级别的驱动程序之后调用 IoReleaseRemoveLockAndWait,并在它释放内存之前调用 IoDetachDevice 或调用 IoDeleteDevice。 为特定的删除锁调用 IoReleaseRemoveLockAndWait 后,针对同一删除锁对 IoAcquireRemoveLock 的所有后续调用都将失败。

IoReleaseRemoveLockAndWait 返回后,驱动程序应将设备视为处于已准备好删除且无法执行 I/O 操作的状态。 因此,驱动程序不得调用 IoInitializeRemoveLock 来重新初始化删除锁。 驱动程序验证程序验证驱动程序时违反此规则将导致 bug 检查。

由于驱动程序将 IO_REMOVE_LOCK 结构存储在设备对象的设备扩展中,因此当驱动程序在处理 IRP_MN_REMOVE_DEVICE 请求时删除设备扩展时,删除锁将被删除。