中断就是产生的一个电信号.好比键盘.当按下就会产生电信号发送给CPU
而CPU就会中止当前处理.去执行电信号.他是根据IRQL中断级别来进行处理的.
以下图:
函数
中断说白了就是个电信号.打断CPU执行的代码. 去调用中断处理函数.
此时CPU就处于硬件上下文.spa
由于会产生不少CPU电信号.全部硬件同是发送中断处理级别怎么办.因此须要为这些级别分一个优先级. CPU会先执行优先级高的.会把优先级低的给屏蔽掉.线程
当CPU处于中断上下文的时候. CPU不能是阻塞的/阻塞. 没有进程能够调度.code
了解CPU的上下文.至少脑海须要有印象blog
上下文 | 说明 | |
---|---|---|
中断上下文 | CPU代替硬件作某些事情. | |
进程上下文 | CPU代替进程作某些事情. |
中断级别了解
以下图:
进程
软件中只会处理下面三种级别.
DISPATCH_LEVEL最高
APC_LEVEL 其次
PASSIVE_LEVEL最低内存
1.查询MSDN.MSDN最下面有IRQL级别的说明.回调函数
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 放到咱们代码块中便可.