使用驱动程序验证程序识别高级用户的 Windows 驱动程序问题

驱动程序验证程序工具包含在自 Windows 2000 以来的每个 Windows 版本中。 它用于检测和排查许多已知会导致系统损坏、故障或其他不可预测的行为的驱动程序问题。 本文介绍如何使用驱动程序验证程序对系统中的驱动程序进行隔离和故障排除。

适用于:Windows Server 2012 Foundation、Windows Server 2012 Essentials、Windows Server 2012 Standard、Windows Server 2012 Datacenter
原始 KB 编号: 244617

驱动程序验证程序功能

若要使用驱动程序验证程序,请运行 Verifier.exe,然后重新启动计算机。 无需进行任何其他更改即可开始分析系统中的驱动程序。 用户帐户需要管理员权限才能运行 Verifier.exe。

驱动程序验证程序可以检查驱动程序行为的多个不同方面。 这些功能分组到通过使用标志启用的选项或设置中。 (驱动程序验证程序文档中的术语选项、设置和标志通常可互换。它们表示类似的概念。)

有关每个标志的详细信息,请参阅 驱动程序验证程序选项和规则类

标准选项

以下选项共同表示系统中的所有驱动程序都不应违反的规则。 如果选择在驱动程序验证程序 GUI 中启用标准设置,或者在使用命令行配置驱动程序验证程序时指定开关, /standard 则启用这些选项。

自动检查

无论选择了哪些选项,这些检查始终对正在验证的驱动程序执行。

自动检查示例:

  • IRQL 检查
    • 引发的 IRQL (表示当前 IRQL 小于目标 IRQL) 。
    • 降低的 IRQL (表示当前 IRQL 大于目标 IRQL) 。
  • SpinLocks:
    • 旋转锁的双重释放。
    • 在相应的 IRQL 处进行自旋锁获取/发布。
  • 内存分配:
    • 分页池分配/释放是在正确的 IRQL (APC_LEVEL 或低于) 进行。
    • 非分页池分配/释放是在正确的 IRQL (DISPATCH_LEVEL 或低于) 进行。
    • 不会 (API) 这些应用程序编程接口指定任何随机 (未初始化) 值。
    • 释放的分配不指向活动计时器对象。
  • 驱动程序卸载检查:
    • 验证驱动程序在卸载时是否没有挂起的操作,例如挂起的 DPC 或工作线程。
  • 其他驱动程序行为:
    • 不正确地切换线程堆栈。
    • 尝试在 IRQL >= DISPATCH_LEVEL 调用 KeWaitXxx。
    • 取消引用已具有 0 引用计数的对象。

特殊池

当此选项处于活动状态时,驱动程序验证程序将从特殊池分配驱动程序的大部分内存请求。 此特殊池受到内存溢出、内存不足和释放后访问的内存的监视。

强制 IRQL 检查

当此选项处于活动状态时,驱动程序验证程序会使可分页代码失效,从而对驱动程序施加极大的内存压力。 如果驱动程序尝试在错误的 IRQL 处访问分页内存,或者在持有旋转锁时,驱动程序验证程序会检测到此行为。

池跟踪

当此选项处于活动状态时,驱动程序验证程序会检查驱动程序在卸载时是否已释放其所有内存分配。 它显示内存泄漏。

I/O 验证

当此选项处于活动状态时,驱动程序验证程序将从特殊池分配驱动程序的 IRP,并监视驱动程序的 I/O 处理。 它检测 I/O 例程的非法或不一致的使用。

启用 I/O 验证程序后:

  • 通过 IoAllocateIrp 分配的所有 IRP 均从特殊池分配(如果可用)。
  • 在 IoCallDriver、IoCompleteRequest 和 IoFreeIrp 中会进行检查,以捕获驱动程序错误消息。
  • 所有 I/O 验证程序失败的 bug 检查代码DRIVER_VERIFIER_IOMANAGER_VIOLATION (0xC9) 。

注意

在 Windows 7 及更高版本的 Windows 操作系统中,增强型 I/O 验证的所有功能都作为 I/O 验证的一部分包含在 I/O 验证中,并且不再需要在驱动程序验证程序管理器或命令行中选择增强型 I/O 验证选项。

死锁检测

当此选项处于活动状态时,驱动程序验证程序将监视驱动程序对旋转锁、互斥锁和快速互斥的使用情况。 它会检测驱动程序的代码是否可能在某些时候导致死锁。

增强的 I/O 验证

当此选项处于活动状态时,驱动程序验证程序将监视多个 I/O 管理器例程的调用,并执行 PnP IRP、电源 IRP 和 WMI IRP 的压力测试。

注意

在 Windows 7 及更高版本中,增强型 I/O 验证的所有功能都作为 I/O 验证的一部分包含在内。 在驱动程序验证程序管理器或命令行中,此选项不再可用或是必需的。

DMA 验证

当此选项处于活动状态时,驱动程序验证程序将监视驱动程序对 DMA 例程的使用。 它检测 DMA 缓冲区、适配器和映射寄存器的不当使用。

安全检查

当此选项处于活动状态时,驱动程序验证程序会查找可能导致安全漏洞的常见错误,例如内核模式例程引用用户模式地址。

杂项检查

当此选项处于活动状态时,驱动程序验证程序会查找驱动程序崩溃的常见原因,例如释放内存处理不当。

DDI 符合性检查

当此选项处于活动状态时,驱动程序验证程序将应用一组设备驱动程序接口 (DDI) 规则,这些规则检查驱动程序与操作系统的内核接口之间的正确交互。

DDI 符合性检查选项通过使用名为 VerifierExt.sys 的内核模式库来实现。 如果发现违反 DDI 符合性检查规则之一,VerifierExt.sys 将是调用系统 bug 检查发生的模块。

其他选项

这些选项设计用于特定的方案测试,或者是将故障或延迟注入某些 DDI 例程以模拟极端压力条件的选项。

驱动程序验证程序要求

唯一的要求是必须安装Windows Server 2012。 可以在零售版和已检查版 Windows 上启用驱动程序验证程序。 如果已安装诺顿防病毒,请不要启用驱动程序验证程序的死锁检测。

启用驱动程序验证程序

可以使用 Verifier.exe 启用驱动程序验证程序。 Verifier.exe 包含在每个 Windows 副本中。 它会自动安装到 System32 文件夹中。 Verifier.exe 具有命令行和图形用户界面 (GUI) 接口,因此可以指定驱动程序和适当的验证级别。 还可以实时查看驱动程序验证程序统计信息。 有关详细信息,请参阅 驱动程序验证程序管理器 (Verifier.exe) 部分。

调试驱动程序验证程序冲突

如果驱动程序验证程序检测到冲突,则标准行为是检查系统 bug,以提供有关调试问题的最多信息。 一旦出现 bug 检查,连接到调试器的系统将停止。

所有驱动程序验证程序冲突都会导致 bug 检查,最常见的 (尽管不一定全部) 是:

  • 0xC1:SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION
  • 0xC4:DRIVER_VERIFIER_DETECTED_VIOLATION
  • 0xC6:DRIVER_CAUGHT_MODIFYING_FREED_POOL
  • 0xC9:DRIVER_VERIFIER_IOMANAGER_VIOLATION
  • 0xD6:DRIVER_PAGE_FAULT_BEYOND_END_OF_ALLOCATION
  • 0xE6:DRIVER_VERIFIER_DMA_VIOLATION

!analyze -v 是在启动新的调试会话时使用的最佳命令。 此命令将返回有用的信息,并尝试查明故障驱动程序。

特定于驱动程序验证程序的调试器扩展:

  • !verifier 将转储捕获的驱动程序验证程序统计信息。 !verifier -? 将显示所有可用选项。
  • !deadlock 转储与死锁检测跟踪的锁或对象相关的信息。 !deadlock -? 将显示所有可用选项。
  • !iovirp [address] 将转储与 I/O 验证程序跟踪的 IRP 相关的信息。
  • !ruleinfo [RuleID]将转储与违反的 DDI 符合性检查规则相关的信息, (RuleID 始终是 bug 检查的第一个参数,所有 DDI 合规性检查规则 ID 的格式为 0x200nn) 。

驱动程序验证器和图形驱动程序

Windows 内核模式图形驱动程序(如打印机和显示驱动程序 DLL)被限制为直接调用池入口点。 使用图形设备驱动程序接口间接执行池分配, (DDI) 回调到 Win32k.sys。 例如,EngAllocMem 是图形驱动程序调用以显式分配池内存的回调。 其他专用回调(如 EngCreatePalette 和 EngCreateBitmap)也返回池内存。

为了为图形驱动程序提供相同的自动测试,Win32k.sys 中整合了对某些驱动程序验证器函数的支持。 由于图形驱动程序比其他内核模式驱动程序更受限制,因此它们只需要一部分驱动程序验证程序功能。 具体而言,不需要 IRQL 检查和 I/O 验证。 其他功能(即使用特殊池、池分配的随机故障和池跟踪)在不同的图形 DDI 回调中受到不同程度的支持。

以下图形 DDI 回调函数支持随机故障:

  • EngAllocMem
  • EngAllocUserMem
  • EngCreateBitmap
  • EngCreateDeviceSurface
  • EngCreateDeviceBitmap
  • EngCreatePalette
  • EngCreateClip
  • EngCreatePath
  • EngCreateWnd
  • EngCreateDriverObj
  • BRUSHOBJ_pvAllocRbrush
  • CLIPOBJ_ppoGetPath

此外,EngAllocMem 支持使用特殊池和池跟踪。

为图形驱动程序启用驱动程序验证程序与其他驱动程序相同。 有关详细信息,请参阅 启用驱动程序验证程序 部分。 不支持的标志(如 IRQL 检查)将被忽略。 此外,可以使用 !gdikdx.verifier 内核调试器命令检查图形驱动程序的当前驱动程序验证程序状态和池跟踪。

注意

只应将随机分配失败设置用于可靠性测试。 使用此设置可能会导致呈现错误消息,因此不应将此设置与验证测试结合使用来检查图形驱动程序实现的正确性 (例如,通过将图形驱动程序输出与引用图像进行比较) 。

驱动程序验证程序管理器 (Verifier.exe)

驱动程序验证程序管理器工具 (Verifier.exe) 是创建和修改驱动程序验证程序设置以及从驱动程序验证程序收集统计信息的首选方法。 对于每个 Windows 安装,Verifier.exe 位于 %WinDir%\System32 文件夹中。

驱动程序验证程序管理器是 Windows 随附的 GUI,用于配置驱动程序验证程序。 使用 verifier.exe 启动驱动程序验证程序管理器,无需任何其他命令行开关。 每当包含开关时,将使用基于命令行的实用工具版本。

有关配置驱动程序验证程序的帮助,请从管理员 CMD 窗口运行 verifier.exe /?

驱动程序状态

“驱动程序状态”属性页提供驱动程序验证程序的当前状态的图像。 可以查看验证程序检测到的驱动程序。 状态可以是以下值之一:

  • 已加载:驱动程序当前已加载并验证。
  • 卸载:驱动程序当前未加载,但自重启计算机以来至少加载了一次。
  • 从不加载:从未加载驱动程序。 此状态可以指示驱动程序的映像文件已损坏,或者你指定了系统中缺少的驱动程序名称。

选择列表标题,按驱动程序名称或状态对列表进行排序。 在对话框的右上方区域,可以查看有效的当前验证类型。 如果不切换到手动刷新模式,驱动程序的状态会自动更新。 可以使用对话框左下角区域中的单选按钮修改刷新率。 若要强制更新状态,请选择“ 立即更新”。

如果启用特殊池标志,并且只有不到 95% 的池分配进入了特殊池,则此页上会显示一条警告消息。 这意味着需要选择一组较小的驱动程序进行验证,或向计算机添加更多物理内存,以获得池分配验证的更好覆盖范围。

全局计数器

此属性页显示驱动程序验证程序维护的某些计数器的当前值。 计数器的零值可能指示未启用关联的驱动程序验证程序标志。 例如,“其他/故障”计数器的值为 0 表示未启用低资源模拟标志。 可以监视验证程序的活动,因为默认情况下会自动更新计数器的值。 可以更改刷新率、切换到手动刷新,或使用对话框左下角区域中的控件组强制刷新。

池跟踪

此属性页显示从驱动程序验证程序收集的更多统计信息。 此页上显示的所有计数器都与验证者的池跟踪标志相关。 其中大多数是每个驱动程序的计数器,例如当前分配、当前分配的字节等。 必须从顶部组合框中选择驱动程序名称,才能查看该特定驱动程序的计数器。

设置

可以使用此页面创建和修改驱动程序验证程序设置。 设置保存在注册表中,必须重新启动计算机才能使设置生效。 可以使用列表查看当前安装的驱动程序。 每个驱动程序可能处于以下状态之一:

  • 验证已启用:驱动程序当前已验证。
  • 验证已禁用:驱动程序当前未验证。
  • 验证启用 (需要重新启动) :仅在下次重启后验证驱动程序。
  • 验证禁用 (需要重新启动) :驱动程序当前已验证,但在下次重启后未验证。

可以从列表中选择一个或多个驱动程序,并使用列表下的两个按钮切换状态。 还可以右键单击驱动程序名称以显示上下文菜单,以便执行状态切换。

在对话框底部,可以指定要在下一次重启后验证的更多驱动程序 (用空格分隔) 。 当你想要安装尚未加载的新驱动程序时,通常使用此编辑控件。

如果列表顶部的单选按钮组设置为 “验证所有驱动程序”,则列表和“验证”和“不验证”按钮以及编辑控件不可用。 这意味着,下次重启后,系统会验证系统中的所有驱动程序。

可以使用对话框右上角区域中的检查框设置验证类型。 可以在级别 1 或级别 2 上启用 I/O 验证。 级别 2 验证比级别 1 强。

通过选择“ 应用”保存对设置的任何修改。 此页中还有两个按钮:

  • 首选设置:它选择一些常用设置, (所有已验证) 驱动程序。
  • 全部重置:它将清除所有驱动程序验证程序设置,以便不验证驱动程序。

选择“ 应用”后,必须重新启动计算机才能使更改生效。

易失性设置

可以使用此属性页立即更改驱动程序验证程序标志。 只能切换某些驱动程序验证程序标志的状态。 并且无法更改要验证的驱动程序的列表。 更改某些检查框的状态后,选择“应用”,使更改生效。 更改将立即生效。 它们持续到你进行其他更改或重启计算机为止。

命令行接口

还可以从命令行 (运行 Verifier.exe,有关详细信息,请在命令提示符) 键入 verifier.exe /? 。 可以在命令行上使用多个开关,例如:

Verifier.exe /flags 0x209BB /driver MyDriver1.sys MyFilterDriver1.sys

以下列表显示了最常用的命令行标志:

配置选项 (标志)

  • verifier.exe /flags

    是十六进制数, (需要 0x 前缀,) 表示要启用的标志的集合值。 输出中显示了每个标志的值 verifier /?

    标准标志:

    0x00000000:自动检查
    0x00000001:特殊池
    0x00000002:强制 IRQL 检查
    0x00000008:池跟踪
    0x00000010:I/O 验证
    0x00000020:死锁检测
    0x00000080:DMA 检查
    0x00000100:安全检查
    0x00000800:杂项检查
    0x00020000:DDI 符合性检查

    更多标志:

    0x00000004:随机低资源模拟
    0x00000040:增强的 I/O 验证 (Vista)
    0x00000200:强制挂起的 I/O 请求
    0x00000400:IRP 日志记录
    0x00002000:堆栈的固定 MDL 检查
    0x00004000:driver0x00008000 的固定 MDL 检查:Power Framework 延迟模糊

    例如,若要仅启用特殊池、I/O 验证和其他检查,请执行以下操作:

    verifier.exe /flags 0x811
    

    若要启用所有标准设置 (任一示例) 有效:

    verifier.exe /standard
    
    verifier.exe /flags 0x209BB
    
  • 配置要验证的驱动程序

    verifier.exe /driver driver1.sys [driver2.sys driver3.sys ...]
    

    此命令指定要验证的特定驱动程序。 在以空格分隔的列表中提供其他驱动程序。

    verifier.exe /all
    

    此命令验证系统中的所有驱动程序。

  • 使用易失性模式进行配置

    verifier.exe /volatile /flags *value /adddriver MyDriver1.sys*
    

    此命令会立即更改验证程序标志,并添加用于验证 MyDriver1.sys。

  • 查询当前验证程序统计信息

    verifier /query
    

    将当前驱动程序验证程序状态和计数器转储到标准输出。

  • 查询当前验证程序设置

    verifier /querysettings
    

    将当前驱动程序验证程序设置转储到标准输出。

  • 清除验证程序设置

    verifier.exe /reset
    

    此命令将清除所有当前的驱动程序验证程序设置。

面向驱动程序开发人员的其他信息

以下部分介绍了驱动程序开发人员可能感兴趣的驱动程序验证程序设置的更多详细信息。 IT 专业人员通常不需要这些设置。

重要

此部分(或称方法或任务)介绍了修改注册表的步骤。 但是,注册表修改不当可能会出现严重问题。 因此,请务必严格按照这些步骤操作。 为了加强保护,应先备份注册表,再进行修改。 如果出现问题,可以还原注册表。 有关如何备份和还原注册表的详细信息,请参阅如何备份和还原 Windows 中的注册表

若要通过编辑注册表启用驱动程序验证程序,请执行以下步骤:

  1. 启动注册表编辑器 (Regedt32) 。

  2. 找到以下注册表项:

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\VerifyDrivers

  3. REG_SZ编辑密钥。

REG_SZ 键设置为要测试的驱动程序不区分大小写的名称。 可以指定多个驱动程序,但只能使用一个驱动程序。 通过这样做,可以确保可用系统资源不会过早耗尽。 资源过早耗尽不会导致任何系统可靠性问题,但可能会导致绕过某些驱动程序检查。

以下列表显示了键的值 REG_SZ 示例:

  • Ntfs.sys
  • Win32k.sys ftdisk.sys
  • *.sys

可以在以下注册表项中指定驱动程序验证级别:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\VerifyDriverLevel

键的值是一个 DWORD,表示启用的所有标志的集合。