Monday, April 30, 2012

IRQL科普


IRQL是Interrupt ReQuest Level,中断请求级别。处理器在一个IRQL上执行线程代码。IRQL是帮助决定线程如何被中断的。在同一处理器上,线程只能被更高级别IRQL的线程能中断。每个处理器都有自己的中断IRQL。常见的IRQL级别有四个:Passive、APC、 Dispatch、DIRQL。

PASSIVE_LEVEL
IRQL最低级别,没有被屏蔽的中断,线程执行用户模式,可以访问分页内存。

APC_LEVEL
只有APC级别的中断被屏蔽,可以访问分页内存。当有APC发生时,处理器提升到APC级别,这样,就屏蔽掉其它APC,为了和APC执行 一些同步,驱动程序可以手动提升到这个级别。比如,如果提升到这个级别,APC就不能调用。在这个级别,APC被禁止了,导致禁止一些I/O完成APC, 所以有一些API不能调用。

DISPATCH_LEVEL
DPC(延迟过程) 和更低的中断被屏蔽,不能访问分页内存,所有的被访问的内存不能分页。因为只能处理分页内存,所以在这个级别,能够访问的API大大减少。

DIRQL (Device IRQL)
通常处于高层次的驱动程序不会使用这个IRQL等级,在这个等级上所有的中断都会被忽略。这是IRQL的最高等级,通常使用这个来判断设备的优先级。

KeLowerIrql与KeRaiseIrql
可以先提升IRQL,然后恢复(下降)到原有IRQL;不能单独调用KeLowerIrql来降低IRQL;调用了KeRaiseIrql后必须调用KeLowerIrql恢复原有IRQL。

 void RasieIRQL_Test()
{
    KIRQL oldIrql;
    //确保当前IRQL等于或小于DISPATCH_LEVEL
    ASSERT(KeGetCurrentIrql()<= DISPATCH_LEVEL);
    //提升IRQL至DISPATCH_LEVEL,并将先前的IRQL保存
    KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
    //...
    //恢复到先前的IRQL
    KeLowerIrql(oldIrql);
}

KeRaiseIrql
If the new IRQL is less than the current IRQL, a bug check occurs. Otherwise, the current IRQL is set to the specified value.
Callers of this routine can be running at any IRQL. Any caller should restore the original IRQL with KeLowerIrql as soon as possible.
A call to KeLowerIrql is valid if it specifies NewIrql <= CurrentIrql. A call to KeRaiseIrql is valid if the caller specifies NewIrql >= CurrentIrql.

KeLowerIrql
It is a fatal error to call KeLowerIrql using an input NewIrql that was not returned by the immediately preceding call to KeRaiseIrql.

Reference
PEDIY: http://bbs.pediy.com/showthread.php?t=84588
MSDN

原创文章,转载请注明:
本文出自程序人生 >> IRQL科普
作者:代码疯子

No comments:

Post a Comment