第一卷驱动程序编写者指南 第1章驱动程序开发环境 第2章测试驱动程序
1 第一卷 驱动程序编写者指南 第 1 章 驱动程序开发环境 第 2 章 测试驱动程序
第1章驱动程序开发环境 为 Microsoft Windows82000开发驱动程序至少需要两台机器:一台用于开发,一台用于调 试 如果驱动程序依赖于基本设备,包括高端工作站和服务器,驱动程序也可在一台多处理器计 算机上调试和测试。 本章讨论如下主题: 1.1自由构建( Free Build)和检查构建( Checked build 1.2调试环境 1.1自由构建和检查构建 微软的 Windows2000驱动程序的测试和调试需要 Windows82000的自由构建和检查构建 自由构建(或零星构建)是操作系统的终端用户版本,系统和驱动程序以最优化方式构建, 不可用调试断言,且调试信息已从二进制码中去除。自由系统和驱动程序更小更快,对内存 的需求更小。 检査构建用于操作系统和内核模式驱动程序的测试和调试,检査构建包括意外错误检査、参 数检查和在自由构建中不可用的调试信息。一个检查的系统或驱动程序能帮助区分和记录驱 动程序的某些问题,如内存泄漏或不当的设备配置,这些问题将导致不可预测的后果。 尽管检查构建提供额外的保护,但它比自由构建消耗更多的内存和硬盘空间,且由于下列原 因,系统和驱动程序运行得更慢 可执行程序含有符号调试信息。 由于参数检查和调试输出,执行了附加的代码(诊断信息)。 新的驱动程序开发通常包括以下步骤 1.编写驱动程序代码,应包括条件编译标记的调试检査。 2.测试和调试基于操作系统的检査构建的驱动程序的检查构建。 3.测试和调试基于自由构建的驱动程序的自由构建。 4.基于自由构建的驱动程序的调整 5.使用了检查构建和自由构建的驱动程序和操作系统附加的测试和调试。 6.使用了自由构建的最终的测试和检查。 在驱动程序开发的早期,需要 Windows2000检查构建来调试驱动程序,检查构建的附加调试 代码保护了驱动程序可能导致的许多错误(比如复发的自旋锁)。 执行调整、最终测试和检査驱动程序应该基于自由构建而完成,自由构建的速度越快越有可 能发现竞争条件和其他同步性的问题。 由于自由构建与 Windows2000的零星版本相同,最终测试和检查也应该基于自由构建而完 驱动程序代码通常包括预处理器符号,该符号允许被编译成自由和检查构建。 DBG标记是一个保留的符号,可用它来决定编译时 Windows2000的什么构建在运行,如果
2 第1章 驱动程序开发环境 为 Microsoft® Windows® 2000 开发驱动程序至少需要两台机器:一台用于开发,一台用于调 试。 如果驱动程序依赖于基本设备,包括高端工作站和服务器,驱动程序也可在一台多处理器计 算机上调试和测试。 本章讨论如下主题: ◼ 1.1 自由构建(Free Build)和检查构建(Checked Build) ◼ 1.2 调试环境 1.1 自由构建和检查构建 微软的 Windows2000 驱动程序的测试和调试需要 Windows® 2000 的自由构建和检查构建。 ◼ 自由构建(或零星构建)是操作系统的终端用户版本,系统和驱动程序以最优化方式构建, 不可用调试断言,且调试信息已从二进制码中去除。自由系统和驱动程序更小更快,对内存 的需求更小。 ◼ 检查构建用于操作系统和内核模式驱动程序的测试和调试,检查构建包括意外错误检查、参 数检查和在自由构建中不可用的调试信息。一个检查的系统或驱动程序能帮助区分和记录驱 动程序的某些问题,如内存泄漏或不当的设备配置,这些问题将导致不可预测的后果。 尽管检查构建提供额外的保护,但它比自由构建消耗更多的内存和硬盘空间,且由于下列原 因,系统和驱动程序运行得更慢。 ◼ 可执行程序含有符号调试信息。 ◼ 由于参数检查和调试输出,执行了附加的代码(诊断信息)。 新的驱动程序开发通常包括以下步骤: 1. 编写驱动程序代码,应包括条件编译标记的调试检查。 2. 测试和调试基于操作系统的检查构建的驱动程序的检查构建。 3. 测试和调试基于自由构建的驱动程序的自由构建。 4. 基于自由构建的驱动程序的调整。 5. 使用了检查构建和自由构建的驱动程序和操作系统附加的测试和调试。 6. 使用了自由构建的最终的测试和检查。 在驱动程序开发的早期,需要 Windows2000 检查构建来调试驱动程序,检查构建的附加调试 代码保护了驱动程序可能导致的许多错误(比如复发的自旋锁)。 执行调整、最终测试和检查驱动程序应该基于自由构建而完成,自由构建的速度越快越有可 能发现竞争条件和其他同步性的问题。 由于自由构建与 Windows2000 的零星版本相同,最终测试和检查也应该基于自由构建而完 成。 驱动程序代码通常包括预处理器符号,该符号允许被编译成自由和检查构建。 DBG 标记是一个保留的符号,可用它来决定编译时 Windows2000 的什么构建在运行,如果
Windows2000检查构建运行,设置DBG为1,如果自由构建运行,不定义DBG(或设置为0,如 果或者包括头文件wdmh,或者包括 ntddk h)。 驱动程序也应该在至少一个多处理器平台和至少一个单处理器平台上测试和调试:且这两个 平台应该运行 Windows2000的当前版本。 12调试环境 内核模式调试需要一个目标机和一个主机,目标机用来运行驱动程序或另一内核模式的应用 程序,主机运行调试程序。 图1.1显示使用调试驱动程序的典型 Windows2000设置。内核调试不需要自由或检查构建的 特别结合,从一自由或检査系统调试一自由系统或检査系统是可行的。然而,总体上说,主机没 有理由运行较慢的检查构建。 图1.1典型的 Windows2000调试设置 参看在线DDK的 Debugging drivers和微软的调试程序使用文献来获得更多细节
3 Windows2000 检查构建运行,设置 DBG 为 1,如果自由构建运行,不定义 DBG(或设置为 0,如 果或者包括头文件 wdm.h ,或者包括 ntddk.h)。 驱动程序也应该在至少一个多处理器平台和至少一个单处理器平台上测试和调试;且这两个 平台应该运行 Windows2000 的当前版本。 1.2 调试环境 内核模式调试需要一个目标机和一个主机,目标机用来运行驱动程序或另一内核模式的应用 程序,主机运行调试程序。 图 1.1 显示使用调试驱动程序的典型 Windows2000 设置。内核调试不需要自由或检查构建的 特别结合,从一自由或检查系统调试一自由系统或检查系统是可行的。然而,总体上说,主机没 有理由运行较慢的检查构建。 图 1.1 典型的 Windows2000 调试设置 参看在线 DDK 的 Debugging Drivers 和微软的调试程序使用文献来获得更多细节
第2章检查驱动程序 在 Windows2000上, Driver verifier是新的可用工具,它执行几项测试和调试内核模式驱动程 序的任务 2.1 Driver Verifier Driver verifier是一可帮助监视一个或多个内核模式驱动程序以证实他们没有非法函数调用 或引起系统讹误的工具, Driver Verifier在目标驱动程序上执行广泛的测试和检査任务。例如,如 果驱动程序以非正当的IRQL使用了内存,不正当地调用或释放自旋锁和内存分配,或者释放内 存池时没有首先删除任何定时器, Driver verifier将发布合适的错误检查。 当未装载驱动程序时, Driver Verifier检査确信驱动程序已经正确地清理了队列、线程和其他 项目 此外, Driver verifier能够执行以下任何情况 ■从一个特别内存池分配驱动程序内存请求,该过程测试驱动程序是否访问它的内存分配之外 的内存,或者在释放它的分配之后访问内存。 通过使内存分页代码无效而给驱动程序极端的内存压力,这个过程揭示了访问分页内存的企 图,分页的内存发生在当错误的IRQL或当保留一自旋锁时 池分配的随机失效或其他的内存请求,该过程测试了驱动程序处理低内存状况的能力 未装载的驱动程序检查所有的内存分配,以确信驱动程序没有漏掉内存。 从一特别池分配驱动程序的IRP,监视驱动程序IO以处理其他不一致的行为 这些能力可以分别激活或禁止,此外, Driver verifier可同时用于任何数目的驱动程序。 下面的部分解释了驱动程序的工作方面 2.1.1 Driver verifier的能力 详细描述了 Driver verifier各个作用,它应用于除过图形驱动程序之外的所有内核模式驱动程 ■2.1.2图形驱动程序的 Driver verifier的能力 描述了 Driver verifier对内核模式图形驱动程序的作用,这里内核模式图形驱动程序使用了图 形驱动程序接口(GD)。 ■2.1.3激活和监视 Driver verifier 解释了怎样启动 Driver verifier,怎样选择所要的功能,怎样选择所要检査的驱动程序,也解 释了如何利用 Driver verifier manager来监视正被检查的驱动程序的行为。 注意: Driver verifier能够检査任何数目的驱动程序,然而,当特别内存池和IO检査选项同 时运用于一驱动程序时,其效果将更为有效
4 第2章 检查驱动程序 在 Windows2000 上,Driver Verifier 是新的可用工具,它执行几项测试和调试内核模式驱动程 序的任务。 2.1 Driver Verifier Driver Verifier 是一可帮助监视一个或多个内核模式驱动程序以证实他们没有非法函数调用 或引起系统讹误的工具,Driver Verifier 在目标驱动程序上执行广泛的测试和检查任务。例如,如 果驱动程序以非正当的 IRQL 使用了内存,不正当地调用或释放自旋锁和内存分配,或者释放内 存池时没有首先删除任何定时器,Driver Verifier 将发布合适的错误检查。 当未装载驱动程序时,Driver Verifier 检查确信驱动程序已经正确地清理了队列、线程和其他 项目。 此外,Driver Verifier 能够执行以下任何情况: ◼ 从一个特别内存池分配驱动程序内存请求,该过程测试驱动程序是否访问它的内存分配之外 的内存,或者在释放它的分配之后访问内存。 ◼ 通过使内存分页代码无效而给驱动程序极端的内存压力,这个过程揭示了访问分页内存的企 图,分页的内存发生在当错误的 IRQL 或当保留一自旋锁时。 ◼ 池分配的随机失效或其他的内存请求,该过程测试了驱动程序处理低内存状况的能力。 ◼ 未装载的驱动程序检查所有的内存分配,以确信驱动程序没有漏掉内存。 ◼ 从一特别池分配驱动程序的 IRP,监视驱动程序 I/O 以处理其他不一致的行为。 这些能力可以分别激活或禁止,此外,Driver Verifier 可同时用于任何数目的驱动程序。 下面的部分解释了驱动程序的工作方面: ◼ 2.1.1 Driver Verifier 的能力 详细描述了 Driver Verifier 各个作用,它应用于除过图形驱动程序之外的所有内核模式驱动程 序。 ◼ 2.1.2 图形驱动程序的 Driver Verifier 的能力 描述了 Driver Verifier 对内核模式图形驱动程序的作用,这里内核模式图形驱动程序使用了图 形驱动程序接口(GDI)。 ◼ 2.1.3 激活和监视 Driver Verifier 解释了怎样启动 Driver Verifier,怎样选择所要的功能,怎样选择所要检查的驱动程序,也解 释了如何利用 Driver Verifier Manager 来监视正被检查的驱动程序的行为。 注意:Driver Verifier 能够检查任何数目的驱动程序,然而,当特别内存池和 I/O 检查选项同 时运用于一驱动程序时,其效果将更为有效
211 Driver verifier的能力 Driver Verifier有两种能力:一种是一直起作用,另一种只有被选择时才起作用 以下是对 Driver verifier所有能力的描述 ■2.1.1.1自动检查 这些是一直起作用的功能,比如IRQL和内存例程的检查,检查定时器检查释放的内存池, 检查驱动程序的正确卸载。 21.1.2特别内存池 这个功能使用了一个特别池来测试内存的上溢和下溢,及在内存释放之后的访问。 ■2.1.1.3强迫IRQL检查 这个功能给驱动程序极端的内存压力来揭示内存分页的故障。 2.1.1.4低资源模拟 这个功能注入随机分配错误和其他被拒决的请求来测试驱动程序在低内存状况下的响应。 2.1.1.5内存池跟踪 这个功能检查当驱动程序被卸载时所有内存分配已经释放。 ■2.1.1.6I/O检查 这个功能监视驱动程序IO对非法或不一致的行为的处理。 21.1.1自动检查 不论 Driver verifier检查一个或多个驱动程序,它将执行以下功能,这些功能不受任何 Driver Verifier选项的允许和禁止之影响。 IRQL和内存例程的检查 Driver verifier为下面被禁止的功能而监视所选择的驱动程序。 通过调用 KeLowerIrql提高IRQL 通过调用 KeRaiselrql降低IRQL 零内存分配请求 在 APC LEVER之上的IRQL分配和释放分页池 在 DIPATCH LEVER之上的IRQL分配和释放非分页池 尝试释放一个没有从前面的分配里返回的地址 尝试释放一个已被释放的地址。 ■在 APC LEⅤER之上的在IRQL获取和释放一个快速的互斥体 ■在IRQL而非在 DIPATCH LEⅤER之上获取和释放一个自旋锁 双倍释放一个自旋锁 指定一非法或随机(未初始化的)参数给任一API。 如果 Driver verifier没有运行,在所有状况下,这些故障不大可能会引起立即的系统崩溃,如 果以上任何故障发生,则 Driver verifier监视驱动程序的行为并发布错误检测αxC4。(参看微软调 试程序文档的使用来获得错误检查参数。) 检查被释放的内存池定时器 Driver verifier检查所有被检查驱动程序所释放的内存池,如果任何定时器保留在该池里,发 布错误检测0xC7。(遗忘的定时器能导致最终系统崩溃,这是最难考虑到的。)
5 2.1.1 Driver Verifier 的能力 Driver Verifier 有两种能力:一种是一直起作用,另一种只有被选择时才起作用。 以下是对 Driver Verifier 所有能力的描述: ◼ 2.1.1.1 自动检查 这些是一直起作用的功能,比如 IRQL 和内存例程的检查,检查定时器检查释放的内存池, 检查驱动程序的正确卸载。 ◼ 2.1.1.2 特别内存池 这个功能使用了一个特别池来测试内存的上溢和下溢,及在内存释放之后的访问。 ◼ 2.1.1.3 强迫 IRQL 检查 这个功能给驱动程序极端的内存压力来揭示内存分页的故障。 ◼ 2.1.1.4 低资源模拟 这个功能注入随机分配错误和其他被拒决的请求来测试驱动程序在低内存状况下的响应。 ◼ 2.1.1.5 内存池跟踪 这个功能检查当驱动程序被卸载时所有内存分配已经释放。 ◼ 2.1.1.6 I/O 检查 这个功能监视驱动程序 I/O 对非法或不一致的行为的处理。 2.1.1.1 自动检查 不论 Driver Verifier 检查一个或多个驱动程序,它将执行以下功能,这些功能不受任何 Driver Verifier 选项的允许和禁止之影响。 IRQL 和内存例程的检查 Driver Verifier 为下面被禁止的功能而监视所选择的驱动程序。 ◼ 通过调用 KeLowerIrql 提高 IRQL ◼ 通过调用 KeRaiseIrql 降低 IRQL ◼ 零内存分配请求 ◼ 在 APC_LEVER 之上的 IRQL 分配和释放分页池 ◼ 在 DIPATCH_LEVER 之上的 IRQL 分配和释放非分页池 ◼ 尝试释放一个没有从前面的分配里返回的地址。 ◼ 尝试释放一个已被释放的地址。 ◼ 在 APC_LEVER 之上的在 IRQL 获取和释放一个快速的互斥体 ◼ 在 IRQL 而非在 DIPATCH_LEVER 之上获取和释放一个自旋锁 ◼ 双倍释放一个自旋锁 ◼ 指定一非法或随机(未初始化的)参数给任一 API。 如果 Driver Verifier 没有运行,在所有状况下,这些故障不大可能会引起立即的系统崩溃,如 果以上任何故障发生,则 Driver Verifier 监视驱动程序的行为并发布错误检测 0xC4。(参看微软调 试程序文档的使用来获得错误检查参数。) 检查被释放的内存池定时器 Driver Verifier 检查所有被检查驱动程序所释放的内存池,如果任何定时器保留在该池里,发 布错误检测 0xC7。(遗忘的定时器能导致最终系统崩溃,这是最难考虑到的。)