0

我对设备移除有疑问。

当我们想通知 PnP 管理器设备已消失时,我们IoInvalidateDeviceRelations使用BusRelations. 之后,操作系统将发送IRP_MN_QUERY_DEVICE_RELATIONS带有BusRelations. 在这个请求处理程序中,我们将从数组中排除设备,并将做另一项必要的工作来“断开”它与总线的连接,我们还将RemovePending在其设备扩展中设置标志。

我不明白如何在设备变为“删除待处理”之后和操作系统发送请求之前处理传入设备的 IO 请求IRP_MN_REMOVE_DEVICE。我们应该检查RemovePending标志并返回STATUS_DEVICE_DOES_NOT_EXIST还是应该像往常一样继续?

现在想象一下,IRP_MN_REMOVE_DEVICE请求终于到达了。MSDN说我们必须调用IoReleaseRemoveLockAndWait释放当前获取的remove lock,防止后续获取,等待现有获取被释放。所以它迫使我们总是在 PnP 请求处理程序中获取删除锁IoAcquireRemoveLockIoReleaseRemoveLockAndWait并用forIRP_MN_REMOVE_DEVICE或 with IoReleaseRemoveLockfor 另一个次要代码释放它。

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

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

4

1 回答 1

1

之后,操作系统将发送IRP_MN_QUERY_DEVICE_RELATIONS带有 BusRelations. 在这个请求处理程序中,我们将从数组中排除设备,并将做另一项必要的工作来“断开”它与总线的连接,我们还将RemovePending在其设备扩展中设置标志。

这里只需要从数组中排除设备并RemovePending在其设备扩展中设置标志。但是做另一项必要的工作来“断开”它与总线的连接 - 仅在您处理时才需要做(在总线驱动程序对请求IRP_MN_REMOVE_DEVICE的最新响应中未包含设备之后- 或者换句话说 - 当其设备扩展中的标志时)IRP_MN_QUERY_DEVICE_RELATIONSBusRelationsRemovePending

如何在设备变为“删除待处理”之后和操作系统发送请求之前处理对设备的传入 IO 请求IRP_MN_REMOVE_DEVICE。我们应该检查RemovePending标志并返回 STATUS_DEVICE_DOES_NOT_EXIST还是应该像往常一样继续?

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

我们真的可以使用 Run-Down Protection 来代替 Remove Locks,几乎以与 Remove Locks 相同的方式、完全相同的位置和相同的原因。我认为 Run-Down Protection api(更多新的比较删除锁) - 更好的设计和更好的使用(但不同的是最小的)

我不明白为什么我们需要在 PnP 请求处理程序中获取删除锁?

首先请注意,关于删除锁仅在Removing a Device in a Function Driver 中说。你我怎么理解没有功能,但总线驱动程序 - 所以在总线驱动程序中删除设备更适合你。并且在删除功能驱动程序中的设备的文档中存在严重错误- 建议首先在第 4 点调用IoReleaseRemoveLockAndWait-8之前- 将请求传递给下一个驱动程序。但必须是正确的IRP_MN_REMOVE_DEVICE

驱动程序应该IoReleaseRemoveLockAndWait IRP_MN_REMOVE_DEVICE请求传递给下一个较低的驱动程序之后、释放内存、调用IoDetachDevice或调用之前调用 IoDeleteDevice

这是正确的,在Using Remove LocksIoReleaseRemoveLockAndWait中有说明。有趣的是,在旧的 msdn 版本中是

IoReleaseRemoveLockAndWait 在它通过之前打电话..

但现在这是固定的。为什么之后?因为下一个较低的驱动程序可以挂起一些 IRP(我们在其上调用IoAcquireRemoveLockor ExAcquireRundownProtection)并且仅在得到IRP_MN_REMOVE_DEVICE并且我们的驱动程序调用IoReleaseRemoveLockExReleaseRundownProtection仅当该 IRP 将完成时才完成它。结果,如果调用IoReleaseRemoveLockAndWaitExWaitForRundownProtectionRelease 之前将删除 IRP 传递给下一个较低的驱动程序 - 我们可以在这里永远等待 - 下一个较低的驱动程序无法完成某些 IRP(直到没有得到删除请求)并且我们不会释放删除锁定或中断保护。

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

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

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

于 2017-08-01T17:23:51.600 回答