PnP 驱动程序中的 WDM 设备删除

WDM device removal in PnP driver

我对移除设备有疑问。

当我们想通知 PnP 管理器设备已经消失时,我们用 BusRelations 调用 IoInvalidateDeviceRelations。之后 OS 将发送 IRP_MN_QUERY_DEVICE_RELATIONS 请求 BusRelations。在此请求处理程序中,我们将从数组中排除设备,并将执行另一项必要的工作以从总线 "disconnect" 它,我们还将在其设备扩展中设置 RemovePending 标志。

我不明白如何处理在设备变为 "remove pending" 之后和 OS 发送 IRP_MN_REMOVE_DEVICE 请求之前向设备传入的 IO 请求。我们应该检查 RemovePending 标志和 return STATUS_DEVICE_DOES_NOT_EXIST 还是应该照常进行?

现在想象一下 IRP_MN_REMOVE_DEVICE 请求终于到了。 MSDN 说我们必须调用 IoReleaseRemoveLockAndWait 来释放当前获取的 remove lock,阻止后续获取并等待现有获取被释放。因此,它迫使我们始终使用 IoAcquireRemoveLock 在 PnP 请求处理程序中获取移除锁;并用 IoReleaseRemoveLockAndWait 释放 IRP_MN_REMOVE_DEVICE 或用 IoReleaseRemoveLock 释放另一个次要代码。

我不明白为什么我们需要在 PnP 请求处理程序中获取移除锁?以我的理解,我们只需要为挂起的 irp 获取删除锁,并在此类 irp 完成时释放它。所以 Windows 人们可以为我们提供 IoWaitForExistingRemoveLocks 例程而不是 IoReleaseRemoveLockAndWait

对不起,如果有点乱,我就是想不通。谢谢。

After that OS will send IRP_MN_QUERY_DEVICE_RELATIONS request with BusRelations. In this request handler we will exclude device from array and will do another necessary job to "disconnect" it from bus, also we will set RemovePending flag in its device extension.

这里只需要从数组中排除设备并在其设备扩展中设置RemovePending标志。但是从总线上对它进行另一项必要的工作 "disconnect" - 仅当您处理 IRP_MN_REMOVE_DEVICE 时才需要做(在设备未包含在总线驱动程序对 IRP_MN_QUERY_DEVICE_RELATIONS 请求的最新响应中 BusRelations - 或者换句话说 - 当 RemovePending 在其设备扩展中标记时)

how to deal with incoming IO requests to the device after it becomes "remove pending" and before OS sends IRP_MN_REMOVE_DEVICE request. Should we check RemovePending flag and return STATUS_DEVICE_DOES_NOT_EXIST or should we proceed as usual?

我认为这两种行为都有可能 - 您可以像往常一样处理它,也可以 return STATUS_DEVICE_DOES_NOT_EXIST。并假设下一种情况 - 您在移除设备过程中同时收到一些 IO 请求。当您检查 RemovePending 标志时 - 它尚未设置。然后您开始处理请求 "as usual"。但是在您检查 IO 请求中的 RemovePending 标志之后,您可以在使用 BusRelations 处理 IRP_MN_QUERY_DEVICE_RELATIONS 请求时设置它。这种情况与使用Remove Locks or Run-Down Protection的感觉直接相关。

我们真的可以使用 运行-Down Protection 来代替 Remove Locks,几乎以与 Remove Locks 相同的方式、完全相同的位置和相同的原因。我认为 运行-向下保护 api(更多新的比较移除锁)-更好的设计和更好的使用(但差异很小)

I don't understand why we need to acquire remove lock inside PnP request handler?

首先要注意关于移除锁只在Removing a Device in a Function Driver. you how i understand have not function, but bus driver- so Removing a Device in a Bus Driver more suitable for you. and in documentation for Removing a Device in a Function Driver exist serious error - advice first call IoReleaseRemoveLockAndWait4 - before点[=92] =]8 - 将 IRP_MN_REMOVE_DEVICE 请求传递给下一个驱动程序。但正确的必须是

driver should call IoReleaseRemoveLockAndWait after it passes the IRP_MN_REMOVE_DEVICE request to the next-lower driver, and before it releases memory, calls IoDetachDevice, or calls IoDeleteDevice.

这是正确的,并在 Using Remove Locks and IoReleaseRemoveLockAndWait 中说明。有趣的是,在旧的 msdn 版本中是

call IoReleaseRemoveLockAndWait before it passes..

但现在这个问题已经解决了。为什么之后?因为下一个较低的驱动程序可以挂起一些 IRP(我们调用 IoAcquireRemoveLockExAcquireRundownProtection)并且只有在得到 IRP_MN_REMOVE_DEVICE 并且我们的驱动程序调用 IoReleaseRemoveLock 或 [=37 时才完成它=] 仅当此 IRP 完成时。结果,如果调用 IoReleaseRemoveLockAndWaitExWaitForRundownProtectionRelease before 将删除 IRP 传递给下一个较低的驱动程序 - 我们可以在这里永远等待 - 下一个较低的驱动程序无法完成一些 IRP(直到没有收到删除请求)并且我们不会释放删除锁定或中断保护。

所以我们需要移除锁或破旧保护?因为我们可以同时获得 IRP_MN_REMOVE_DEVICE 和另一个 IO 请求。并且此 IO 请求可以使用 设备上的一些资源。当我们处理 IRP_MN_REMOVE_DEVICE 时,我们从另一个大小 销毁 这个资源。如果我们在他将在 IRP_MN_REMOVE_DEVICE 中被销毁后在 IO 请求中使用一些资源会怎样?认为不需要回答。为防止这种情况存在移除锁或停机保护。在使用任何资源(将在删除中销毁)之前需要调用 IoAcquireRemoveLockExAcquireRundownProtection 并且只有在状态正常 returned 时才使用它。在我们完成使用资源调用 IoReleaseRemoveLockExReleaseRundownProtection 之后。在 IRP_MN_REMOVE_DEVICE 中我们调用 IoReleaseRemoveLockAndWaitExWaitForRundownProtectionRelease。在这个调用被 returned 之后 - 我们可以确定没有人使用我们的资源并且永远不会被更多地使用(调用 IoAcquireRemoveLockExAcquireRundownProtection return 错误状态(false) ).此时我们可以安全地开始销毁资源:释放内存(等),调用 IoDetachDeviceIoDeleteDevice.

指向下一个低层设备的指针——这也是资源,我们在进程IO请求中使用,在销毁IRP_MN_REMOVE_DEVICE(通过调用 IoDetachDevice)。在调用IoDetachDevice(_nextDeviceObject);(在IRP_MN_REMOVE_DEVICE内)之后调用IofCallDriver(_nextDeviceObject, Irp);(在处理一些IO请求时)真的是正确的吗?因为这个移除锁(或者我在这里使用你自己的 rundown-protection )总是用在函数和过滤驱动中。对于总线驱动程序,我们通常没有指向下一个较低设备的指针(PDO 未附加到另一个设备,当 FDO 附加到 PDO 和过滤器总是附在某物上)——可能不需要锁(或根本不需要停机保护)。这取决于 - 是否存在另一种资源 - 使用和销毁(在移除时)。

对于总线设备 - 通常情况下我们得到 IRP_MN_REMOVE_DEVICE 2 次 - 首先是在设备标记为 RemovePending 之前 - 所以我们转到第 4 点。在设备标记为 [=12= 之后](因此设备未包含在总线驱动程序对 BusRelations 的 IRP_MN_QUERY_DEVICE_RELATIONS 请求的最新响应中)我们最终销毁资源并调用 IoDeleteDevice