删除锁IO_REMOVE_LOCK与STATUS_DELETE_PENDING
删除锁IO_REMOVE_LOCK很少见,但很重要。
其结构体定义为:
typedef struct _IO_REMOVE_LOCK {
IO_REMOVE_LOCK_COMMON_BLOCK Common;
#if DBG
IO_REMOVE_LOCK_DBG_BLOCK Dbg;
#endif
} IO_REMOVE_LOCK, *PIO_REMOVE_LOCK
再分析:
typedef struct _IO_REMOVE_LOCK_COMMON_BLOCK {
BOOLEAN Removed;
BOOLEAN Reserved [3];
__volatile LONG IoCount;
KEVENT RemoveEvent;
} IO_REMOVE_LOCK_COMMON_BLOCK;
typedef struct _IO_REMOVE_LOCK_DBG_BLOCK {
LONG Signature;
ULONG HighWatermark;
LONGLONG MaxLockedTicks;
LONG AllocateTag;
LIST_ENTRY LockList;
KSPIN_LOCK Spin;
__volatile LONG LowMemoryCount;
ULONG Reserved1[4];
PVOID Reserved2;
PIO_REMOVE_LOCK_TRACKING_BLOCK Blocks;
} IO_REMOVE_LOCK_DBG_BLOCK;
这里主要关注结构体IO_REMOVE_LOCK_COMMON_BLOCK,其有2个关键的变量IoCount和RemoveEvent。可以看到,一个是计数,另一个是事件。所以总结一下,删除锁IO_REMOVE_LOCK其实就是一个微软对事件和引用计数的一个封装。
删除锁IO_REMOVE_LOCK和普通自旋锁一样,需要初始化,使用的函数为IoInitializeRemoveLock,在正常使用其,其也有相应的获取自旋锁IoAcquireRemoveLock和释放自旋锁IoReleaseRemoveLock。不过这个锁相对于其它锁,有一个特别的函数IoReleaseRemoveLockAndWait,此函数通常在 IRP_MN_REMOVE_DEVICE中调用,当调用该函数之后会等待RemoveEvent的事件,如果返回则可以开始执行IoDetachDevice, or calls IoDeleteDevice。
另外,如果调用了IoReleaseRemoveLockAndWait这后,这时再调用IoAcquireRemoveLock,之后会返回STATUS_DELETE_PENDING,表示驱动程序已收到设备的IRP_MN_REMOVE_DEVICE,并已调用IoReleaseRemoveLockandWait。
删除锁IO_REMOVE_LOCK微软提供的示例包括
- event示例
C:\WinDDK\7600.16385.1\src\general\event\wdm
- filter示例
C:\WinDDK\7600.16385.1\src\general\toaster\wdm\filter
微软对其有权微解释可详见:https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/using-remove-locks
另外 IO_REMOVE_LOCK使用方法小结一文https://www.shuzhiduo.com/A/Vx5MxmWYJN/ 也有说明。这里把它提示的示例代码展示出来: