在 KMDF 和 UMDF 2 驱动程序中使用即时跟踪记录器 (IFR)

从 Windows 10 开始,你可以生成 KMDF 或 UMDF 驱动程序,以便它通过 Windows 软件跟踪预处理获取额外的驱动程序调试信息。 从 KMDF 版本 1.15 和 UMDF 版本 2.15 开始,此功能称为 Inflight 跟踪记录器(IFR)。

飞行跟踪记录器是 WPP 软件跟踪扩展。 与 WPP 跟踪不同,Inflight 跟踪记录器在不使用附加跟踪使用者的情况下继续工作。 框架将消息写入循环缓冲区,驱动程序还可以添加自己的消息。 每个驱动程序都有自己的日志,因此与驱动程序关联的多个设备共享单个日志。

如果在驱动程序二进制文件中启用 IFR,则在驱动程序的生命周期内,IFR 会始终存在并处于运行状态。 不需启动显式跟踪收集会话。

日志存储在不可分页的内存中,因此在系统崩溃后可恢复这些日志。 此外,在小型转储文件中包括 Inflight Trace Recorder 日志,除非责任驱动程序不确定或崩溃是否为主机超时。

如何启用 Inflight 跟踪记录器并从驱动程序发送消息

  1. 在 Microsoft Visual Studio 中,执行以下步骤:

    • 打开驱动程序项目的属性页。 在“解决方案资源管理器”中右键单击驱动程序项目,并选择“属性”。 在驱动程序的属性页中,选择“配置属性”,然后选择“Wpp 跟踪”。“常规”菜单上,将“运行 WPP 跟踪”设置为”。

    • 导航到 Properties-Wpp 跟踪函数和宏选项,然后选择“启用 WPP 记录器”。>>

    • 在同一菜单上,将扫描配置数据设置为包含跟踪信息的文件,例如 Trace.h。

  2. 在每个调用 WPP 宏的源文件中,添加一个标识跟踪消息标头(TMH)文件的 #include 指令。 文件名必须具有 driver-source-file-name.tmh> 的格式。<

    例如,如果驱动程序包含两个名为 MyDriver1.cMyDriver2.c 的源文件,则 MyDriver1.c 必须包含:

    #include“MyDriver1.tmh”

    MyDriver2.c 必须包含:

    #include“MyDriver2.tmh”

    在 Visual Studio 中生成驱动程序时,WPP 预处理器将生成 .tmh 文件。

  3. 在头文件中定义WPP_CONTROL_GUIDS宏。 此宏定义驱动程序跟踪消息的 GUID 和 跟踪标志

    Osrusbfx2 驱动程序示例定义 Trace.h 头文件中的单个控件 GUID 和 7 个跟踪标志,如以下示例所示:

    #define WPP_CONTROL_GUIDS \
    WPP_DEFINE_CONTROL_GUID(OsrUsbFxTraceGuid, \
      (d23a0c5a,d307,4f0e,ae8e,E2A355AD5DAB), \
      WPP_DEFINE_BIT(DBG_INIT)          /* bit  0 = 0x00000001 */ \
      WPP_DEFINE_BIT(DBG_PNP)           /* bit  1 = 0x00000002 */ \
      WPP_DEFINE_BIT(DBG_POWER)         /* bit  2 = 0x00000004 */ \
      WPP_DEFINE_BIT(DBG_WMI)           /* bit  3 = 0x00000008 */ \
      WPP_DEFINE_BIT(DBG_CREATE_CLOSE)  /* bit  4 = 0x00000010 */ \
      WPP_DEFINE_BIT(DBG_IOCTL)         /* bit  5 = 0x00000020 */ \
      WPP_DEFINE_BIT(DBG_WRITE)         /* bit  6 = 0x00000040 */ \
      WPP_DEFINE_BIT(DBG_READ)          /* bit  7 = 0x00000080 */ \
    )
    

    在此示例中:

    • OsrUsbFxTraceGuid 是 {d23a0c5a-d307-4f0e-ae8e-E2A355AD5DAB} GUID 的友好名称。
    • 跟踪标志用于区分在驱动程序处理不同类型的 I/O 请求时生成的跟踪消息。
  4. 驱动程序(KMDF 和 UMDF 2)必须使用驱动程序对象和注册表路径(通常来自 DriverEntry)为内核模式驱动程序调用WPP_INIT_TRACING:

    WPP_INIT_TRACING( DriverObject, RegistryPath );
    

    若要停用跟踪,KMDF 和 UMDF 2 驱动程序都从 EvtCleanupCallbackEvtDriverUnload 调用内核模式驱动程序WPP_CLEANUP:

    WPP_CLEANUP( WdfDriverWdmGetDriverObject( Driver ));
    

    WPP_CLEANUP宏采用PDRIVER_OBJECT类型的参数,因此,如果驱动程序的 DriverEntry 失败,则可以跳过调用 WdfDriverWdmGetDriverObject,而是使用指向 WDM 驱动程序对象的指针调用WPP_CLEANUP。

    由于 UMDF 驱动程序使用这些宏的内核模式签名来初始化和清理跟踪,因此调用看起来与 KMDF 和 UMDF 完全相同。

  5. 驱动程序中使用 DoTraceMessage 宏或自定义版本的宏来创建跟踪消息。

    以下示例演示 Osrusbfx2 驱动程序如何在专用于处理读取请求的代码的一部分中使用其 TraceEvents 函数:

    if (Length > TEST_BOARD_TRANSFER_BUFFER_SIZE) {
        TraceEvents(TRACE_LEVEL_ERROR,
                    DBG_READ,
                    "Transfer exceeds %d\n",
                    TEST_BOARD_TRANSFER_BUFFER_SIZE);
    
        status = STATUS_INVALID_PARAMETER;
    }
    

    如果跟踪控制器启用TRACE_LEVEL_ERROR级别和DBG_READ跟踪标志,则对 TraceEvents 的调用将生成跟踪消息。 该消息包括驱动程序定义的常量 TEST_BOARD_TRANSFER_BUFFER_SIZE的值。

  6. 若要更改驱动程序日志使用的循环缓冲区的大小,请修改 以下注册表位置中的 LogPages 注册表值:

    对于 UMDF:

    SOFTWARE\Microsoft\Windows NT\CurrentVersion\WUDF\Services\<YourDriver>\Parameters\Wdf

    对于 KMDF:

    HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\<YourDriver>\Parameters\Wdf

    这是一个类型 为REG_DWORD 的值,其中包含在页面中分配的日志缓冲区的大小。 有效值介于 0x1 和 0x10 之间。

对于 KMDF 驱动程序

  1. 通过在调试器中键入 .load rcdrkd.dll 来加载 RCDRKD 命令。
  2. 使用 !wdfkd.wdfldr 扩展显示有关当前动态绑定到 Windows 驱动程序框架(WDF)的驱动程序的信息。
  3. 使用 !rcdrkd.rcdrlogdump!rcdrkd.rcdrcrashdump 查看驱动程序提供的消息。
  4. 使用 !wdfkd.wdflogdump!wdfkd.wdfcrashdump 查看框架提供的消息。

UMDF 驱动程序的实时调试

  1. 使用 !wdfkd.wdfldr 扩展显示有关当前动态绑定到 WDF 的驱动程序的信息。 查找用户模式驱动程序。 输入关联的主机进程。

  2. 键入 !wdfkd.wdflogdump <YourDriverName.dll><Flag,其中 <Flag>> 为:

    • 0x1 – 合并框架和驱动程序日志
    • 0x2 – 驱动程序日志
    • 0x3 – 框架日志

    如果没有指定驱动程序的驱动程序日志,则扩展仅显示框架日志。

在 UMDF 驱动程序崩溃后查看登录跟踪记录器日志

  1. 在 WinDbg 中,选择 “文件>打开故障转储”,并指定要调试的小型转储文件。

  2. 键入 !wdfkd.wdfcrashdump <YourDriverName.dll><驱动程序主机<>选项的进程 ID,其中 <Option>> 为:

    • 0x1 – 合并框架和驱动程序日志
    • 0x2 – 驱动程序日志
    • 0x3 – 框架日志

    如果未指定驱动程序, !wdfcrashdump 将显示所有驱动程序的信息。 如果未指定主机进程,并且只有一个进程,则扩展将使用单个主机进程。 如果未指定主机进程且有多个进程,则扩展会列出活动主机进程。

    如果存储在小型转储中的日志信息与输入的名称不匹配,则小型转储不包含驱动程序的日志。

如果没有连接调试器,仍可访问驱动程序和框架日志。 若要了解如何操作,请参阅 视频:在没有调试器的情况下访问驱动程序 IFR 日志。

有关将跟踪消息添加到驱动程序的详细信息,请参阅 向驱动程序添加 WPP 宏。

如何启用 UMDF 驱动程序的调试

RCDRKD 扩展

使用框架的事件日志器

在 UMDF 驱动程序中使用 WPP 软件跟踪