64位内核开发第十讲,IRQL中断级别了解

中断级别IROL了解

一丶IRQL

1.了解什么是中断

中断就是产生的一个电信号.好比键盘.当按下就会产生电信号发送给CPU
而CPU就会中止当前处理.去执行电信号.他是根据IRQL中断级别来进行处理的.
以下图:
函数

中断说白了就是个电信号.打断CPU执行的代码. 去调用中断处理函数.
此时CPU就处于硬件上下文.spa

2.IROL中断级别.

由于会产生不少CPU电信号.全部硬件同是发送中断处理级别怎么办.因此须要为这些级别分一个优先级. CPU会先执行优先级高的.会把优先级低的给屏蔽掉.线程

当CPU处于中断上下文的时候. CPU不能是阻塞的/阻塞. 没有进程能够调度.code

了解CPU的上下文.至少脑海须要有印象blog

上下文 说明
中断上下文 CPU代替硬件作某些事情.
进程上下文 CPU代替进程作某些事情.

中断级别了解
以下图:
进程

软件中只会处理下面三种级别.
DISPATCH_LEVEL最高
APC_LEVEL 其次
PASSIVE_LEVEL最低内存

3.遵照IROL编程规范的方式

1.查询MSDN.MSDN最下面有IRQL级别的说明.回调函数

  1. 运行在DISPATHCH_LEVEL级别的上下文.如何调用PASSIVE_LEVEL级别的函数.
    如咱们有一个需求.
    当键盘按下的时候. 键盘的优先级最高. 会运行在DISPATCH_LEVEL级别.可是此时
    按照咱们Ring3编程的想法.你可能会调用ZwCreateFile这个函数进行将按键写入到文件中.
    可是此时咱们若是查询MSDN以后就会发现.其实ZwCreateFile是不能运行在DISPATCH级别的. 此时解决方法 就是建立一个 工做线程. 工做线程中完成
    咱们想要操做的事情.

3.在PASSIVE级别下.咱们可使用任何内存没有限制.it

首先了解下以下表格.

函数 运行级别
DriverEntry Passive级别.
各类派遣函数 Passive级别
完成函数 Dispatch级别
各类NDIS回调函数 Dispatch级别

PASSIVE级别是可使用任何函数和内存
DISPATCH级别只能访问能运行在DISPATCH级别内存.

非分页内存
NONPAGEPOOL 内存是能够在任何级别使用的.

相关申请内存函数为:

ExAllocatePoolWithTag

PAGEDPOOL 分页内存
只能在PASSIVE级别或者APC级别使用.
咱们能够加入一个宏.来判断当前的中断级别.有没有高于APC
产生一个断言.若是当前级别大于APC级别就会报错.

断言宏的意思就是 我决定当前的事就是某事. 若是你不是我指定的.
那么对不起.报错.

使用PAGE_CODE这个宏便可.
其实很简单.宏站看看一下.

#define PAGED_CODE() PAGED_ASSERT(KeGetCurrentIrql() <= APC_LEVEL);


#if (NTDDI_VERSION >= NTDDI_VISTA)
#define PAGED_ASSERT( exp ) NT_ASSERT( exp )
#else
#define PAGED_ASSERT( exp ) ASSERT( exp )
#endif

往下跟不少.....

直到最终

#define NT_ASSERT_ACTION(_exp) \
    ((!(_exp)) ? \
        (__annotation(L"Debug", L"AssertFail", L#_exp), \
         DbgRaiseAssertionFailure(), FALSE) : \
        TRUE)

其实很简单. 首先调用 KeGetCurrentIrql() 这个函数来判断是否小于等于 APC级别.
而后当参数传递给 PAGED_ASSERT(exp)宏. 里面就调用函数进行断言

断言宏只会在Debug版本中有效.让咱们尽快发现问题. 把 PAGE_CODE 放到咱们代码块中便可.

相关文章
相关标签/搜索