中断就是硬件发给CPU的电信号。cpu通过中断处理表调用相关函数处理中断信号,中断分为下面两种
异常
cpu内部中断,IF位保持不变,不关,就是中断标志位不变不关,同时可以相应其他硬件发出中断。,异常也封两种。
故障:比如除0,缺页,越界堆栈段错误。
陷阱:如调试指令int3,溢出等。
中断:
其他硬件发出的中断,中断标志位清零,关中断。分为
非屏蔽中断,计算机内部出错引起的异常
屏蔽中断。
为了确定CPU先处理哪种中断,所以通过优先级的区分来优先处理。
上下文区别:
进程上下文:可理解为内核系统代替进程做一些事情,比如应用层发读写请求到内核,内核做一些事情,可睡眠,睡觉(因为进程是可以调度的)。
中断上下文:可理解为内核系统代替硬件做一些事情,接到中断请求做的事情,其他时候在进程上下文,不可睡眠,受伤(没有调度机制)
遵守
个人理解各个级别级别越高相当于注意点越多,越在靶心,所以要求多,比如只能用非分页,然后不能允许低级别函数。
要清楚驱动中各个函数的中断级别
比如DriverEnty,DriverUnload,各个分发函数,在passive级别,完成函数各种NDIS回调,在Dispatch级别。
要明白调用的API运行级别
本质因为函数内部没有访问分页内存,只要函数访问了分页内存,只能在passive低级别使用。这有一些规律大部分zw开头函数在passive级别。跟IO相关大部分也都在passive级别。
passive级别可以使用任何函数和内存,要求最低。
DISPATCH级别只能访问运行在dispatch级别的API和非分页内存。
NoNPAGEPOOL内存可在任何级别使用
PAGEDOOL只能在passive_level和APC_LEVEL级别使用。
在PASSIVE_LEVEL和APC级别代码中加:PAGED_CODE()宏
#define PAGED_CODE()\ if(KeGetCurrentIRQL()>APC_LEVEL){ kdPrint(("EX:Pageable code called at IRQL %d\n",KeGerCurrentlrql()));\ ASSERT(FALSE);\ }\当我们不知道我们在什么级别时候可以这样判断。
那如果我们想做键盘过滤程序,如何在高IRQL级别下保存文件(文件相关函数都是在PASSIVE_LEVEl,我们是通过完成例程做的)
我们可以在完成例程里开启一个工作者线程。然后操作文件都在这个线程中,工作者线程是PASSIVE_LEVEL级别。