我是新的Windows设备驱动程序编程。 我知道某些操作只能在IRQL PASSIVE_LEVEL
上执行。 例如,Microsoft有这个示例代码来说明如何从内核驱动程序写入文件:
if (KeGetCurrentIrql() != PASSIVE_LEVEL) return STATUS_INVALID_DEVICE_STATE; Status = ZwCreateFile(...);
我的问题是:什么是防止在上面的KeGetCurrentIrql()
检查后引发IRQL? 说一个上下文或线程交换发生,IRQL不能突然变成DISPATCH_LEVEL
当它回到我的驱动程序,然后会导致系统崩溃?
如果这是不可能的,那为什么不直接在DriverEntry
函数中检查IRQL,并且一劳永逸呢?
一个线程的irql只能自己提升。
由于您是从上/下驱动程序调用的,因此当前正在运行的上下文的irql可能会有所不同。 有几个函数可以提高/降低irql。
几个例子:
IRP_MJ_READ
NTSTATUS DispatchRead( __in struct _DEVICE_OBJECT *DeviceObject, __in struct _IRP *Irp ) { // this will be called at irql == PASSIVE_LEVEL ... // we have acquire a spinlock KSSPIN_LOCK lck; KeInititializeSpinLock( &lck ); KIRQL prev_irql; KeAcquireSpinLock( &lck,&prev_irql ); // KeGetCurrentIrql() == DISPATCH_LEVEL KeReleaseSpinLock( &lck, prev_irql ); // KeGetCurrentIrql() == PASSIVE_LEVEL ... }
(Io-)完成例程可以在DISPATCH_LEVEL
调用,所以应该相应地执行。
NTSTATUS CompleteSth(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context) { // KeGetCurrentIrql() >= PASSIVE_LEVEL }
IRQL只能通过设置来以任何有意义的方式进行更改。 有两个“线程特定的”IRQL – PASSIVE_LEVEL和APC_LEVEL。 您可以通过快速互斥等控制进出这些级别,并且上下文切换到您的线程将始终使您处于以前的级别。 以上是“处理器特定的”IRQL。 这是DISPATCH_LEVEL或以上。 在这些级别上下文切换不能发生。 你使用自旋锁等进入这些水平。 ISR将在您的线程中出现在更高的IRQL上,但您无法看到它们。 当他们将控制权交给你时,你的IRQL被恢复。
DriverEntry也被称为PASSIVE_LEVEL。
如果你想在PASSIVE_LEVEL上完成一项工作,那么使用像IoQueueWorkItem这样的函数