我对设备移除有疑问。
当我们要通知PnP经理设备已消失时,我们使用IoInvalidateDeviceRelations
致电BusRelations
。之后,操作系统会向IRP_MN_QUERY_DEVICE_RELATIONS
发送BusRelations
请求。在此请求处理程序中,我们将从数组中排除设备,并将执行另一项必要的工作以将其从总线“断开”,我们还将在其设备扩展中设置RemovePending
标志。
我不明白如何在设备变为“删除待处理”之后以及在OS发送IRP_MN_REMOVE_DEVICE
请求之前处理传入的IO请求。我们应该检查RemovePending
标志并返回STATUS_DEVICE_DOES_NOT_EXIST
还是应该像往常一样继续进行?
现在想象IRP_MN_REMOVE_DEVICE
请求终于到了。 MSDN表示,我们必须调用IoReleaseRemoveLockAndWait
来释放当前的删除锁定,防止后续采集并在发布现有采集时等待。因此它迫使我们始终使用IoAcquireRemoveLock
获取PnP请求处理程序中的删除锁定;并使用IoReleaseRemoveLockAndWait
IRP_MN_REMOVE_DEVICE
或IoReleaseRemoveLock
发布另一个次要代码。
我不明白为什么我们需要在PnP请求处理程序中获取删除锁?根据我的理解,我们需要仅为挂起的irp获取删除锁定,并在完成此类irp时释放它。因此,Windows用户可以为我们提供IoWaitForExistingRemoveLocks
例程,而不是IoReleaseRemoveLockAndWait
。
对不起,如果它有点乱,我就是想不出来。感谢。
答案 0 :(得分:0)
之后,操作系统将发送
IRP_MN_QUERY_DEVICE_RELATIONS
请求BusRelations
。在此请求处理程序中,我们将从中排除设备 数组,并将做另一项必要的工作,以及#34;断开"从公共汽车, 我们也会在其设备扩展名中设置RemovePending
标志。
此处只需要从数组中排除设备,并在其设备扩展中设置RemovePending
标志。但要做另一项必要的工作,以便断开"它来自总线 - 只有在您处理IRP_MN_REMOVE_DEVICE
时(在设备未包含在总线驱动程序中的最新响应IRP_MN_QUERY_DEVICE_RELATIONS
BusRelations
请求之后)或另一个单词 - 当设备扩展名中有RemovePending
标志时)
如何在设备成功后处理传入的IO请求 "删除待处理"在OS发送
IRP_MN_REMOVE_DEVICE
请求之前。 我们应该检查RemovePending
标志并返回STATUS_DEVICE_DOES_NOT_EXIST
还是应该像往常一样继续进行?
我认为这两种行为都有可能 - 您可以像往常一样处理它并且也可以返回STATUS_DEVICE_DOES_NOT_EXIST
。并假设下一个情况 - 您在删除设备进程的同时获得了一些IO请求。当你检查RemovePending
标志时 - 它尚未设置。并且像往常一样开始处理请求""。但在您检查IO请求中的RemovePending
标志后,您可以在使用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中说明。你怎么理解没有功能,但公交车司机 - 所以Removing a Device in a Bus Driver更适合你。在Removing a Device in a Function Driver的文档中存在严重错误 - 建议首先在 4 - 点IoReleaseRemoveLockAndWait
> 8 - 将IRP_MN_REMOVE_DEVICE
请求传递给下一个驱动程序。但必须正确
驱动程序应在传递后调用
IoReleaseRemoveLockAndWait
IRP_MN_REMOVE_DEVICE
请求下一个较低的驱动程序,以及 在它释放内存,调用IoDetachDevice
或调用之前IoDeleteDevice
。
这是正确的,并在Using Remove Locks和IoReleaseRemoveLockAndWait中说明。有趣的是,旧的msdn版本是
在传递之前致电
IoReleaseRemoveLockAndWait
..
但现在这是固定的。为什么之后?因为下一个较低的驱动程序可以等待一些IRP(我们称之为IoAcquireRemoveLock
或ExAcquireRundownProtection
)并仅在获得IRP_MN_REMOVE_DEVICE
并且我们的驱动程序调用{{1}}或{{1}时完成它只有当这个IRP完成时才会这样。因此,如果在之前调用IoReleaseRemoveLock
或ExReleaseRundownProtection
将删除IRP传递给下一个更低级别的驱动程序,我们可以永久等待 - 下一级驱动程序无法完成某些IRP(直到没有删除请求)并且我们不释放删除锁定或破坏保护。
那么我们需要删除锁定或断开保护?因为我们可以将IoReleaseRemoveLockAndWait
与其他IO请求同时发送。并且此IO请求可以使用设备上的某些资源。当我们处理ExWaitForRundownProtectionRelease
时,我们销毁这些资源。如果我在IRP_MN_REMOVE_DEVICE
中将其销毁后将在IO请求中使用某些资源,该怎么办?认为不需要回答。用于防止此现象并存在移除锁定或断开保护。在使用任何资源(将在删除时销毁)之前,需要调用IRP_MN_REMOVE_DEVICE
或IRP_MN_REMOVE_DEVICE
并仅在返回ok状态时使用它。在我们完成使用资源调用IoAcquireRemoveLock
或ExAcquireRundownProtection
之后。在IoReleaseRemoveLock
我们致电ExReleaseRundownProtection
或IRP_MN_REMOVE_DEVICE
。返回此调用后 - 我们可以确定没有人使用我们的资源,也不会再使用更多(调用IoReleaseRemoveLockAndWait
或ExWaitForRundownProtectionRelease
返回错误状态(false))。此时我们可以安全地开始销毁资源:释放内存(等),调用IoAcquireRemoveLock
,ExAcquireRundownProtection
。
指向下一个较低设备的指针 - 这也是资源,我们在进程IO请求中使用,在IoDetachDevice
中销毁(通过调用{ {1}})。确实是正确的电话IoDeleteDevice
(处理一些IO请求时) 之后调用IRP_MN_REMOVE_DEVICE
(在IoDetachDevice
内)?因为这个删除锁(或我在这里使用自己的rundown-protection)总是在函数和过滤器驱动程序中使用。对于总线驱动程序,我们通常没有指向下一个较低设备的指针( PDO 未连接到另一个设备,当 FDO 连接到 PDO 时并且过滤器始终附着在某物上) - 可能不需要锁(或根本不需要保护)。这取决于 - 存在另一种资源 - 使用和销毁(删除时)。
和总线设备 - 我们得到IofCallDriver(_nextDeviceObject, Irp);
2次时的常见情况 - 首先在设备标记为IoDetachDevice(_nextDeviceObject);
之前 - 所以我们转到第4点并在设备标记为IRP_MN_REMOVE_DEVICE
之后(所以设备没有包含在总线驱动程序的最近响应中对IRL_MN_QUERY_DEVICE_RELATIONS请求的BusRelations)我们最终销毁资源并调用IRP_MN_REMOVE_DEVICE