我是Windows设备驱动程序编程的新手。我知道某些操作只能在IRQL PASSIVE_LEVEL
执行。例如,Microsoft有一个如何从内核驱动程序写入文件的示例代码:
if (KeGetCurrentIrql() != PASSIVE_LEVEL)
return STATUS_INVALID_DEVICE_STATE;
Status = ZwCreateFile(...);
我的问题是:在上面的KeGetCurrentIrql()
检查后,是什么阻止了IRQL的引发?假设发生了上下文或线程切换,当IRQL返回到我的驱动程序时会突然变为DISPATCH_LEVEL
,这会导致系统崩溃吗?
如果这不可能,那么为什么不检查DriverEntry
函数中的IRQL并且一劳永逸地完成它?
答案 0 :(得分:2)
线程的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
}
答案 1 :(得分:2)
IRQL只能通过设置在您的控制下以任何有意义的方式进行更改。有两个“特定于线程”的IRQL - PASSIVE_LEVEL和APC_LEVEL。您可以使用快速互斥体等控制进出这些级别,并且上下文切换到您的线程将始终保持您之前的水平。以上是“特定于处理器”的IRQL。那是DISPATCH_LEVEL或以上。在这些级别中,不能发生上下文切换。你可以使用自旋锁等进入这些级别。 ISR将在您的线程上更高的IRQL上发生,但您无法看到它们。当他们将控制权交还给您时,您的IRQL就会恢复。
答案 2 :(得分:0)
还在PASSIVE_LEVEL调用DriverEntry。
如果您想在PASSIVE_LEVEL完成工作,请使用IoQueueWorkItem
等功能