3.3 驱动异常
初学者开发驱动时,难免会遇到由于代码编写不合规而引发系统崩溃的情况,系统崩溃具体表现为蓝屏(BSOD),蓝屏是Windows系统遇到无法处理的异常或错误时,为了避免错误进一步扩大而触发的保护机制。蓝屏发生时系统将无法继续运行,业务中断,还可能会产生磁盘文件被破坏(数据不完整)等一系列问题。
驱动异常的原因有很多,常见的有:高IRQL死锁、内存访问违例、函数堆栈不平衡等等,不管是由哪种原因导致的,在异常蓝屏的时候,系统都会报告一个异常码,图3-2为一个蓝屏例子。
图3-2 蓝屏界面
在图3-2的蓝屏界面中共有五个信息,其中0x0000007F为异常码,0x0000007F后面括号内的四个值为附加参数,不同异常码和附加参数的含义不同,开发者可以根据这些信息来初步定位异常的类型与发生的大致原因。附加参数的具体含义请读者参考WDK的帮助文档。
除了蓝屏界面显示的异常码,若条件允许,系统会在系统目录生成一个DUMP文件,这个DUMP文件内部保存着蓝屏时刻的异常信息,包括内存、寄存器、异常记录等,开发者可以根据DUMP文件中提供的蛛丝马迹来回溯问题。
最后为读者介绍一个主动引发蓝屏的函数:KeBugCheckEx,这个函数的原型如下:
该函数有五个参数,第一个为异常码,后面四个参数是这个异常码的附加参数,这五个参数信息对应着蓝屏界面的五个信息。读者可以自定义一个异常码,表示一个特定的错误,根据自身需要设置四个附加参数。
KeBugCheckEx函数调用后,系统进入蓝屏界面并停止运行,蓝屏界面会显示BugCheckCode的值以及后面的四个参数,不过对于Windows 10系统来说,蓝屏界面经过优化,不再显示具体参数。
读者可能比较好奇,在什么情况下需要主动触发蓝屏,考虑这样的一个场景:驱动程序处于测试阶段,开发者可以在驱动代码的一些出错处理分支,或者在一些开发者认为不可能出现某种情况的代码分支内添加KeBugCheckEx,在长时间无人工干预的测试过程中,一旦发现代码主动触发蓝屏,开发者可以根据蓝屏的信息重新审视代码逻辑,及时发现问题。另外,发布版本的驱动在发生严重错误的情况下,也会通过KeBugCheckEx触发一个蓝屏,避免错误进一步扩大。