设备驱动程序IRQL和线程/上下文切换

我是新的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这样的函数