windows驱动开发中,感受不少小问题都会致使一些比较麻烦的错误,不少不良习惯均可能会致使系统崩溃。缘由是对内核原理的理解太欠缺了,由于驱动运行在RING0优先级,开发的时候必须至关注意细节,否则调试的时候会很麻烦(有些时候Dump文件分析出来是错误的)。原来我一直奇怪写驱动程序问什么要把有些例程放到非分页内存中,今天算是豁然开朗。只怪原来看内核原理的时候没太仔细。具体缘由是这样的:由于windows的缺页中断处理程序是运行在DISPATCH_LEVEL的级别的。而个人驱动某些例程通常是等于DISPATCH_LEVEL这个中断级别。也就是说。。若是我把个人代码放到分页内存中。。那操做系统极可能在某个时候就把它从物理内存换出到磁盘页面交换文件中了。。而后EIP指针若是访问到的下一个内存页在换页文件中。。那操做系统将产生缺页中断。。而后这缺页中断的级别与个人代码例程是一个级别的。。因此不能被打断。。EIP就会访问的一个错误的内存地址(极可能读/写到了其余进程,也多是系统中重要的数据)上,,用户层的程序内存访问违例的异常操做系统能捕捉到。反馈给用户。。。而在驱动内核层内存访问错误。。这是一个很严重的问题。。操做系统发现当即就以蓝屏的方式处理了。。严重的还致使系统崩溃。就悲剧了。。。另外还有一点就是OS的线程调度程序也运行在这个级别。。这也应该有意识。。否则引发线程切换致使蓝屏也时常发生。。。。。。。。
TIPS:
DISPATCH > APC > PASSIVE
IRQL是Interrupt ReQuest Level,中断请求级别。一个由windows虚拟出来的概念,划分在windows下中断的优先级,这里中断包括了硬中断和软中断,硬中断是由硬件产生,而软中断则是彻底虚拟出来的。
处理器在一个IRQL上执行线程代码。IRQL是帮助决定线程如何被中断的。在同一处理器上,线程只能被更高级别IRQL的线程能中断。每一个处理器都有本身的中断IRQL。
咱们在调用NDIS API时,在DDK帮助文档中都有该API函数的所在级别。
PASSIVE_LEVEL
IRQL最低级别,没有被屏蔽的中断,在这个级别上,线程执行用户模式,能够访问分页内存。
APC_LEVEL
在这个级别上,只有APC级别的中断被屏蔽,能够访问分页内存。当有APC发生时,处理器提高到APC级别,这样,就屏蔽掉其它APC,为了和APC执行一些同步,驱动程序能够手动提高到这个级别。好比,若是提高到这个级别,APC就不能调用。在这个级别,APC被禁止了,致使禁止一些I/O完成APC,因此有一些API不能调用。
DISPATCH_LEVEL
这个级别,DPC 和更低的中断被屏蔽,不能访问分页内存,全部的被访问的内存不能分页。由于只能处理非分页内存,因此在这个级别,可以访问的Api大大减小。windows