Windows 事件跟踪(ETW)是操作系统提供的通用高速跟踪设施。 它使用在内核中实现的缓冲和日志记录机制,为用户模式应用程序和内核模式设备驱动程序引发的事件提供跟踪机制。 此外,ETW 还提供动态启用和禁用日志记录的功能,这使得无需重新启动或应用程序重启即可轻松地在生产环境中执行详细跟踪。 日志记录机制使用异步写入程序线程写入磁盘的每个处理器缓冲区。 此缓冲允许大规模服务器应用程序编写具有最小干扰的事件。
ETW 已在 Windows 2000 中引入。 此后,各种核心操作系统和服务器组件都采用了 ETW 来检测其活动。 ETW 现在是 Windows 平台上的关键检测技术之一。 越来越多的第三方应用程序使用 ETW 进行检测,有些应用程序利用 Windows 提供的事件。 ETW 也已抽象化到 Windows 预处理器(WPP)软件跟踪技术中,该技术提供了一组易于使用的宏,用于跟踪 在开发过程中进行调试的 printf 样式消息。
ETW 已显著升级 Windows Vista 和 Windows 7。 最重要的新功能之一是统一事件提供程序模型和 API。 简言之,新的统一 API 将日志记录跟踪和写入事件查看器合并为事件提供程序的一个一致且易于使用的机制。 同时,ETW 添加了多个新功能,以改善开发人员和最终用户体验。
对 ETW 日志记录的 USB 支持
USB 是将不断增加的外围设备连接到电脑的最普遍手段之一。 USB 主机电脑和 USB 外围设备以及系统供应商、设备供应商和最终用户都期望并要求 USB 设备在系统和设备级别完美运行。
USB 设备的大型安装基础和激增已发现 Windows USB 软件堆栈、USB 主机控制器和 USB 设备之间的兼容性问题。 这些兼容性问题会导致客户出现问题,例如设备操作故障、系统挂起和系统崩溃。
如果没有直接访问系统和/或设备,或者在某些情况下,系统故障转储,就很难或不可能调查和调试 USB 设备问题。 即使完全访问硬件和故障转储,提取相关信息也是一种时间密集型技术,只有少数核心 USB 驱动程序开发人员才知道。 可以使用硬件或软件分析器调试 USB 问题,但它们非常昂贵,并且仅可供一小部分专业人员使用。
USB ETW 支持
ETW 提供了一种事件日志记录机制,USB 驱动程序堆栈可以利用该机制来帮助调查、诊断和调试 USB 相关问题。 USB 驱动程序堆栈 ETW 事件日志记录支持 USB 驱动程序堆栈中现有临时日志记录机制提供的大多数或所有调试功能,没有任何限制。 这可以简化 USB 相关问题的调试,从长远来看,这应该提供更可靠的 USB 驱动程序堆栈。
我们向 USB 主机控制器驱动程序和 USB 中心驱动程序添加了 ETW 日志记录。 USB 主机控制器驱动程序层包括主机控制器端口驱动程序(usbport.sys)和微型端口驱动程序(usbehci.sys、usbohci.sys和usbuhci.sys)。 USB 中心驱动程序层由 USB 中心驱动程序(usbhub.sys)组成。
- USB 中心事件
启用 USB 事件收集时,USB 中心事件提供程序将报告 USB 中心的添加和删除、所有中心的设备摘要事件以及端口状态更改。 可以使用这些事件来确定大多数设备枚举失败的根本原因。
- USB 端口事件
启用 USB 事件收集时,USB 端口事件提供程序从客户端驱动程序报告 I/O、打开和关闭设备终结点,以及微型端口状态转换(如微型端口启动和停止)。 记录的 I/O 包括物理 USB 端口状态的请求。 物理 USB 端口上的状态转换是核心 USB 驱动程序堆栈中活动的关键发起方之一。
Windows 提供 USB 驱动程序堆栈来支持 USB 3.0 设备。 Microsoft提供的 USB 3.0 驱动程序堆栈由三个驱动程序组成:Usbxhci.sys、Ucx01000.sys和Usbhub3.sys。 所有三个驱动程序协同工作,为大多数 USB 3.0 主机控制器向 Windows 添加本机支持。 新的驱动程序堆栈支持 SuperSpeed、高速、全速和低速设备。 通过事件跟踪,USB 3.0 驱动程序堆栈提供主机控制器及其连接到的所有设备的精细活动视图。
- USB Hub3 事件
启用 USB 事件收集时,USB Hub3 事件提供程序报告 USB 中心的添加和删除、所有中心的设备摘要事件、端口状态更改以及 USB 设备和中心的电源状态。 端口状态更改是物理 USB 端口上的状态转换,是核心 USB 驱动程序堆栈中活动的关键发起方之一。 Hub3 报告枚举过程的阶段,这指向大多数设备枚举失败的根本原因。 启用 StateMachine 关键字后,Hub3 会报告软件设备、中心和端口对象的内部状态机活动,从而更深入地了解驱动程序的逻辑。
- USB UCX 事件
启用 USB 事件收集时,USB UCX 事件提供程序从客户端驱动程序报告 I/O,并打开和关闭设备终结点和终结点流。 启用 StateMachine 关键字后,UCX 会报告主机控制器和终结点对象的内部状态机活动,从而更深入地了解驱动程序的逻辑。
- USB xHCI 事件
启用 USB 事件收集时,USB xHCI 事件提供程序报告系统的 xHCI 控制器的属性和 xHCI 操作的低级别详细信息。 xHCI 报告 xHCI 硬件发送到和完成的命令请求,包括特定于 xHCI 的完成代码。
使用 Logman 捕获 USB 事件跟踪
这部分讲解使用 Logman 工具捕获 USB ETW 事件跟踪的信息。 Logman 是内置于 Windows 中的跟踪工具。 可以使用 Logman 将事件捕获到事件跟踪日志文件中。
先决条件
事件跟踪日志文件可以很快增长,但较小的日志文件更易于导航和传输。 在开始跟踪之前,请考虑执行以下步骤从日志中排除无关事件,以便可以专注于要检查的设备活动:
- 断开非相关设备的任何非关键 USB 设备的连接。 设备越少,跟踪越小,更易于阅读和分析;
- 如果系统具有 USB 键盘或鼠标,请改为使用远程桌面输入跟踪命令;
- 在相关操作周围尽可能缩小跟踪的开始和结束范围;
- 如果只对特定类别的 USB 事件感兴趣,可以使用关键字筛选记录的事件;
来自 USB 3.0 驱动程序堆栈的事件跟踪类似于 Windows 7 中引入的 USB 2.0 驱动程序堆栈跟踪。 可以在Windows 8计算机上捕获 USB 2.0 驱动程序堆栈中的事件跟踪。 从 USB 2.0 和 USB 3.0 驱动程序堆栈捕获事件跟踪的方式类似。 可以从 USB 2.0 或 USB 3.0 驱动程序堆栈中独立捕获事件。 将 USB 2.0 设备连接到 USB 3.0 主控制器时,可从 USB 3.0 驱动程序堆栈获取事件跟踪。 在这种情况下,你将查看 USB 2.0 设备的新 USB 3.0 驱动程序堆栈事件。
收集 USB 跟踪事件
1. 打开具有管理权限的命令提示符窗口。 为此,请选择“开始”,在搜索框中键入 cmd ,选择并按住 (或右键单击“) cmd.exe”,然后选择“ 以管理员身份运行”。
2. 在命令提示符窗口中,输入以下命令以启动捕获会话:
logman create trace -n usbtrace -o %SystemRoot%\Tracing\usbtrace.etl -nb 128 640 -bs 128
logman update trace -n usbtrace -p Microsoft-Windows-USB-USBXHCI (Default,PartialDataBusTrace)
logman update trace -n usbtrace -p Microsoft-Windows-USB-UCX (Default,PartialDataBusTrace)
logman update trace -n usbtrace -p Microsoft-Windows-USB-USBHUB3 (Default,PartialDataBusTrace)
logman update trace -n usbtrace -p Microsoft-Windows-USB-USBPORT
logman update trace -n usbtrace -p Microsoft-Windows-USB-USBHUB
logman update trace -n usbtrace -p Microsoft-Windows-Kernel-IoTrace 0 2
logman start -n usbtrace
3. 完成上述每个命令后,Logman 会显示 The command completed successfully.
执行要捕获的操作。 例如,若要捕获设备枚举的事件,可以插入在 设备管理器 中显示为“未知设备”的 U 盘。 使命令提示符窗口保持打开状态。
4. 完成方案后停止会话。 输入以下命令以结束捕获会话:
可以通过运行以下命令来停止 USB 集线器和端口事件收集:
logman stop -n usbtrace
logman delete -n usbtrace
move /Y %SystemRoot%\Tracing\usbtrace_000001.etl %SystemRoot%\Tracing\usbtrace.etl
前面的捕获会话生成名为 usbtrace.etl 的 etl 文件。 跟踪文件存储在 %SystemRoot%\Tracing\usbtrace.etl (C:\Windows\Tracing\usbtrace.etl) 。 将文件移动到另一个位置或将其重命名,以避免在捕获下一个会话时覆盖它。
文件包含来自 USB 3.0 和 USB 2.0 驱动程序堆栈的事件跟踪。 如果要将事件跟踪减少到仅一个 USB 驱动程序堆栈,请从下一个跟踪会话中删除另一个驱动程序堆栈。 为此,可以修改步骤 2 中显示的命令序列,以删除与要从跟踪会话中删除的驱动程序堆栈对应的“logman update”行。
USB 3.0 驱动程序堆栈事件的捕获筛选器
请注意 Logman 捕获命令中的 ETW 关键字,例如 Default 和 PartialDataBusTrace 。 这些字词是 ETW 关键字,用于指示要查看的事件类型。 可以使用 ETW 关键字筛选 USB 驱动程序写入跟踪日志的事件,并自定义要查看的关于从 USB 3.0 驱动程序堆栈捕获的事件的信息量。 保存与任何关键字匹配的事件。 请注意,此筛选方法适用于捕获时,而不是在分析期间使用。
可以根据要求根据关键字筛选事件。 下面是用于筛选 USB 3.0 驱动程序堆栈事件的关键字:
例如,下面是一系列命令,用于启动会话以捕获 USB 设备电源转换。 由于 (USB 3.0 驱动程序堆栈) 选择提供程序,因此仅针对 USB 3.0 主机控制器下游连接的设备捕获事件。
logman create trace -n usbtrace -o %SystemRoot%\Tracing\usbtrace.etl -nb 128 640 -bs 128
logman update trace -n usbtrace -p Microsoft-Windows-USB-USBXHCI (Rundown,Power)
logman update trace -n usbtrace -p Microsoft-Windows-USB-UCX (Rundown,Power)
logman update trace -n usbtrace -p Microsoft-Windows-USB-USBHUB3 (Rundown,Power)
logman update trace -n usbtrace -p Microsoft-Windows-Kernel-IoTrace 0 2
logman start -n usbtrace
电源事件的捕获筛选器
USB 设备的一个有用的 ETW 关键字 (keyword) 是 USB 端口驱动程序的 PowerDiagnostics 标志。 使用此关键字 (keyword) 时,端口驱动程序会记录主机控制器和终结点信息,但省略描述传输的所有事件。 如果不需要查看传输事件,可以使用 PowerDiagnostics 关键字 (keyword) 将跟踪日志的大小减少多达 85%。 启动跟踪时指定 PowerDiagnostics 关键字 (keyword) ,如以下示例所示:
Logman start Usbtrace -p Microsoft-Windows-USB-USBPORT PowerDiagnostics -o usbtrace.etl -ets -nb 128 640 -bs 128
Logman update Usbtrace -p Microsoft-Windows-USB-USBHUB –ets
如果筛选的跟踪日志有许多主机控制器异步计划启用和禁用事件,则可以在使用 Netmon 筛选器查看日志时将其筛选掉,如以下示例所示:
NOT (Description == "USBPort_MicrosoftWindowsUSBUSBPORT:Host Controller Async Schedule Enable"
OR Description == "USBPort_MicrosoftWindowsUSBUSBPORT:Host Controller Async Schedule Disable")
有时,在跟踪日志中显示传输事件会很有帮助,例如导致错误(如 XACT 错误或停止)的中心请求和设备请求。 可以先捕获没有传输事件的日志,然后分析该较小的日志。 在大致了解问题方案中的问题后,再次运行跟踪而不进行筛选。