Windows 事件跟踪

Windows 7,第 1 部分中的核心操作系统事件

Dr. Insung Park 和 Alex Bendetovers

今天的计算机软件经常断开新 grounds。 使用者软件应用程序提供复杂的功能,使新的丰富体验。 功能强大的服务器应用程序吞吐量、 速度和小数位数中设置新记录。 这些改进进行了可能的硬件技术和软件改进优化、 虚拟化,和分布式和并行计算的连续采用快速进行。 不过,缁撴灉软件应用程序已经变得更大、 更复杂。 在同一时间,用户有关软件质量的期望是比以往任何时候都更高。 基本的特征 (如性能、 可靠性和可管理性已证明软件的产品的长期成功非常重要,它们通常庆祝作为主要的功能。

提高软件复杂性和对质量更高的用户期望因此在软件开发过程中提供一个困难的挑战。 将出现是意外的问题,预测的所有相关组件的内部状态时几乎不可能。 retracing 执行流的历史记录是很麻烦和棘手,通常需要找出软件问题的根源。 当用户在部署后报告问题时,它们希望快速确定和解决根本原因的问题。 势不可挡数硬件和软件的组合,不同的工作负荷特征和最终用户的使用模式使这些任务甚至 tougher。 若要使用一种机制使您能够了解系统执行最少的开销具有的一个透明方式,是无价之宝。

事件规范

检测是一类有效的解决方案在测量和提高软件质量。 软件性能计数器提供了一种监视应用程序执行的状态和资源使用的聚合级别的简便方法。 事件检测也已经常用年。 执行的不同阶段的由一个软件组件引发的事件可以显著减少的时间来诊断各种问题。 除了扫描特定事件的模式,一个可以应用数据挖掘和相关技术,以进一步分析事件生成有意义的统计信息和报告程序执行和有问题的行为。 能够在实时的生产系统上收集事件有助于避免在需要的不实用的调试器安装程序在客户计算机上。

在 Windows 2000 操作系统中引入的事件跟踪为 Windows (ETW),可以是常规用途的事件跟踪平台在 Windows 操作系统上。 使用有效的缓冲和日志记录机制实现在内核中,ETW 提供了一个机制保留由用户模式应用程序和内核模式设备驱动程序引发的事件。 此外,ETW 使用户可以启用和禁用动态记录,使其易于生产环境中进行详细的跟踪,而无需重新启动或重新启动的应用程序。

操作系统本身很大程度检测与 ETW 事件中。 能够分析和模拟核心操作系统活动基于开发,ETW 事件,以及生产模式的系统上已有价值的开发人员解决许多质量问题。 每个后续 Windows 版本,该数量 ETW 事件引发鎿嶄綔绯荤粺也增加了 ;Windows 7 最检测的操作系统日期。 鍙 ﹀ 的方式  Windows 7 中包含可以使用分析系统的性能和可靠性,以及发现在软件应用程序中的质量问题杩欎簺鎿嶄綔绯荤粺 ETW 事件的工具。

许多应用程序问题表面为操作系统资源的使用情况,如意外的模式或中的 CPU、 内存、 网络的带宽消耗量的峰值异常 IO,依此类推。 因为原始进程和线程可以跟踪操作系统事件系统的活动,一个可以进行大量的进度中即使没有 ETW 检测应用程序中的许多应用程序问题的根源可能下收缩。 当然,ETW 检测应用程序中的将允许进一步诊断明显更有效。

我们两篇系列文章的第一个项目,我们提供了 ETW 技术和核心操作系统检测的高级概述。 然后,我们将讨论支持工具来获取并使用操作系统的事件。 下一步中,我们提供了在从不同的子组件在核心操作系统中事件的详细信息。 我们还介绍了如何不同系统事件可以被组合以生成全面,我们使用的一组 Windows PowerShell 脚本演示的系统行为的图片。

Windows 事件跟踪

正如前面提到的那样,ETW 将是一个日志记录平台,有效地记录由软件应用程序或内核模式组件发送事件。 使用 ETW 提供程序 API,任何的应用程序 DLL 或驱动程序可以成为事件提供程序 (引发事件的组件) ETW。 提供程序第一次注册通过插入 ETW 记录 API 调用从代码中的各个点的 ETW 和发送事件。 任何可写入的活动的重要性可以是事件,并且它由一条数据由 ETW 写入的日志记录时。 当没有启用提供程序时,将忽略这些日志记录的 API 调用。 ETW 控制器应用程序启动一个 ETW 会话,并使它的某些提供程序。 当启用的事件提供程序进行 API 调用一个日志记录时,事件然后定向到由指定控制器的会话。 事件发送到会话可能会被存储在一个日志文件,在实际的时间内以编程方式使用或一直在内存中,控制器请求到一个文件数据的刷新。 以前的文章"改善调试和性能调整与 ETW"(msdn.microsoft.com/en-us/magazine/dvdarchive/cc163437.aspx),有有关 ETW 技术和如何添加 ETW 检测到应用程序的详细信息。 年,ETW 具有来自支持许多不同的日志记录模式和记录在 MSDN 的功能。

上下文特定的数据后跟一个固定标头包含 ETW 事件。 标头标识事件和引发事件,时特定于上下文的数据 ("事件负载"组件hereafter) 指的是其他任何想要记录的组件引发事件的数据。 由提供程序引发的事件写入到 ETW 会话时, ETW 向其他元数据标头,包括线程和进程 ID,当前 CPU 运行日志记录线程 CPU 时间使用线程,和时间戳中。 图 1 显示 XML 表示形式 (一个进程类型事件的开始) 解码 tracerpt 工具 (将在后面讨论) 作为事件的 XML 转储文件中。 < 系统 >部分常见的所有事件,并代表每个事件的 ETW 记录公共标头。 它包含时间戳、 进程和线程 ID,提供程序 GUID、 CPU 时间、 CPU ID,等等。 < EventData >部分显示记录此事件的负载。 图 1 所示事件从 Windows 鍐呮牳包含进程密钥 (一个唯一密钥分配给每个进程的标识),进程开始处理 ID、 父进程的 ID、 会话 ID,退出 (仅对一个进程结束的事件有效) 的状态、 用户 SID 可执行文件的名称在过程中和启动该进程的命令。

ETW 控制器是使用 ETW 控件 API 的应用程序设置启动 ETW 会话,并启用到那些会话的一个或多个提供程序。 它们需要给予每个会话一个唯一的名称并且 Windows 7 上有 64 个会话同时运行。

图 1 进程启动事件的 XML 转储

<Event xmlns="https://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Guid="{9e814aad-3204-11d2-9a82-006008a86939}" />
<EventID>0</EventID>
<Version>3</Version>
<Level>0</Level>
<Task>0</Task>
<Opcode>1</Opcode>
<Keywords>0x0</Keywords>
<TimeCreated SystemTime="2009-07-14T16:27:43.441456400Z" />
<Correlation ActivityID="
{00000000-0000-0000-0000-000000000000}" />
<Execution ProcessID="2584" ThreadID="4324"
ProcessorID="1" KernelTime="90" UserTime="15" />
<Channel />
<Computer />
</System>
<EventData>
<Data Name="UniqueProcessKey">0xFFFFFA8005BBC950</Data>
<Data Name="ProcessId">0x1430</Data>
<Data Name="ParentId">0xA18</Data>
<Data Name="SessionId"> 1</Data>
<Data Name="ExitStatus">259</Data>
<Data Name="DirectoryTableBase">0x4E1D6000</Data>
<Data Name="UserSID">guest</Data>
<Data Name="ImageFileName">notepad.exe</Data>
<Data Name="CommandLine">notepad</Data>
</EventData>
<RenderingInfo Culture="en-US">
<Opcode>Start</Opcode>
<Provider>MSNT_SystemTrace</Provider>
<EventName xmlns=
"https://schemas.microsoft.com/win/2004/08/events/trace">
Process</EventName>
</RenderingInfo>
<ExtendedTracingInfo xmlns=
"https://schemas.microsoft.com/win/2004/08/events/trace">
<EventGuid>{3d6fa8d0-fe05-11d0-9dda-00c04fd7ba7c}</EventGuid>
</ExtendedTracingInfo>
</Event>

在从内核和核心系统组件但是,记录事件以用户模式应用程序或内核模式设备驱动程序不同的方式。 核心系统将事件记录到特殊会话用一个保留名称 NT 内核记录器。只有"NT 内核记录器"会话 ("内核会话"hereafter) 接收系统中核心的事件,并它不接受来自任何其他常规事件提供程序的事件。 此外,核心操作系统事件是通过指定适当的标志,会话启动时可用的。 每个标志表示可以有选择地启用一个其他核心组件中的事件检测。 这有助于减少在内核中的检测开销,并以系统事件的真实性。 鍙 ﹀ 的方式  Windows 7 中的一个新的功能允许用户在登录时捕获调用堆栈。 如果可用符号,一个可以跟踪触发内核事件记录的函数调用的链。 后面的节中将讨论从调用堆栈分析好处,我们将讨论更多详细信息中的单个事件时。

使用 Windows 上的工具收集的事件

有几个 ETW 控制工具允许用户以收集事件的 Windows 上。 例如,性能监视器公开 ETW 控制一组数据集合的形式。 事件日志服务都还能够启动和停止 ETW 会话以及查看事件。 为命令行脚本的接口 logman.exe 提供选项,以执行 ETW 控制操作。 用于消耗的事件在命令行工具 tracerpt.exe 可以使用 ETW 鏃 ュ 織鏂囦欢和生成几个格式,包括 CSV 和 XML 的转储。 开始处理事件的 XML 表示形式的示例如图 1 所示。 在本文中,我们将使用 logman.exe 和 tracerpt.exe 我们提供的示例中。 提供"logman 查询程序"在的图 2 中的命令列出启用内核会话时可由一个控制器使用不同标记。

下面的命令启动内核会话,并使进程、 线程、 磁盘、 网络、 图像和注册表事件。 将在当前目录中名为 systemevents.etl 文件中存储收集的事件。 控制内核会话和收集核心操作系统事件需要管理员权限:

> logman start "NT Kernel Logger" –p "Windows Kernel Trace" (process,thread,img,disk,net,registry) –o systemevents.etl –ets

要停止集合,用户需要发出,"logman 停止-ets"命令:

> logman stop "NT Kernel Logger" –ets

tracerpt 工具可以处理该日志文件中的事件为可读的格式。 默认情况下, tracerpt 接受一个或多个日志文件和生成事件输出文件和一个摘要文件。 输出文件的默认格式是 XML:

> tracerpt systemevents.etl

在 logman 和 tracerpt 帮助文本、 Windows 帮助和支持,和具有更多开关和功能,这些工具的详细信息的联机文档。

那里被高级性能分析工具的使用各种分析和优化的方案的核心操作系统事件。 Windows 性能Toolkit (WPT) 是这样一种值得注意的工具,可从 Windows SDK (msdn.microsoft.com/en-us/performance/cc825801.aspx)。 WPT 是包括系统集成商、 硬件制造商、 驱动程序开发人员和一般应用程序开发人员在广泛观众有用的。 工具,Xperf 和 XperfView,应用复杂的技术 (包括此处引入) 其跟踪分析聚合和分析提供到操作系统的有意义的视角核心操作系统事件和应用程序的行为。 其灵活的 GUI 提供了很多的格式和自定义演示文稿选项,可以帮助用户关注系统活动的不同方面。 图 3 显示 XperfView 工具的屏幕快照操作中。

核心操作系统事件

Windows 核心操作系统具有许多与 ETW 检测的组件。 的图 2 所示的事件对于都是可用跨越各种子系统包括进程、 线程、 磁盘和文件的内存、 网络,输出输入的注册表等活动的。 在本节中,我们提供了每个组的事件详细信息。 我们还讨论了许多鎿嶄綔绯荤粺的核心概念。 这些概念的详细信息位于中心操作系统的参考资料,如"Windows 内核,第五版,"通过 Russinovitch,索罗门 Ionescu (微软出版社,2009年)。 核心操作系统事件有在将来更改版本的 Windows,作为平台和其检测不断发展以满足新的要求。

有多种将使用的事件数据。 一个可以为某些事件,例如一个错误事件或事件表示执行流模式,扫描。 其他常用方法包括: 统计分析 (计数和概述事件) (分析事件,例如开始和结束的对之间的增量) 的增量分析活动分析 (跟踪通过事件相关的活动/请求),和基于调用堆栈的聚合和模式分析。 年,我们发现它有效构建状态机来模拟操作系统活动时我们核心系统事件。 时我们将介绍此部分中的,系统事件,我们还将说明如何构建状态机中使用它们。

进程、 线程、 图像、 进程计数器的事件

线程是在 Windows 操作系统上执行的基本单位,进程线程的容器。 每个进程 (和线程) 分配的运行时是唯一的 ID。 用于进程和线程 ID 共享相同的数字空间。 也就是活动 ID A 与某个线程时 A 是永远不会提供给其他进程或线程。 唯一的例外且每个 CPU 的空闲线程空闲进程的 ID 是所有相同,在以前已 0。 进程和线程的事件是在建立状态机有助于了解更多高级的系统活动的基本构建基块。 有两个类型的事件的进程和线程的事件:开始和结束。 一个过程的开始和终止分别记录过程开始和结束。 同样适用于线程开始和结束事件。 处理事件的有效负载部分有有关过程,如进程名称和父进程 ID 的详细信息,的图 1 所示。 同样,线程事件负载包含特定于线程的信息下,如堆栈基和限制,和起始地址。 应该注意启动的进程或线程的 ID 是进程和线程事件负载的一部分虽然事件头已有的那些项。 创建当前进程的父进程的上下文中记录进程开始的事件。 在这种情况下将进程 ID < 系统 > 中节 (事件头) 是父进程。 进程 ID 负载是正在创建事件。 同样适用于在线程事件的线程 ID。

进程和收集事件之前启动的线程,ETW 日志状态 rundown 事件。 分析的目的它们用于在开始收集事件的时间表示正在运行的进程和线程。 ETW 还记录 rundown 余下的进程和线程仍在运行集合结束时的事件。 进程和线程 rundown 事件枚举和登录的格式相同的所有进程和包括系统和空闲的进程的线程的进程和线程启动事件的事件。 进程和线程 rundowns 事件用来区分本身和实际的进程和线程创建和终止 DCStart 和 DCEnd,不同类型。 一个进程已终止,但未引用中写入一个单独的已失效事件。

可以使用进程和线程的事件跟踪每个进程和线程在事件收集过程中的活动。 当您生成一个状态机时, 处理例程应保留的活动进程和可能为在程序中的对象的某些类型的线程的列表。 当一个线程或进程终止时,相应的对象可以放置在不同 ("完成") 列表中。 在过程对象还可能包含有关详细信息 (如进程的名称) 的进程所引用,进程和线程事件负载中选取的线程。 它是更简单和很多信息分析,过程中的名称而不是 ID,一个可以引用到的进程 ID 可以终止进程或线程并对它的所有引用都被都释放后回收。 当从其他核心组件的事件指示在状态机构造和模拟的操作系统活动时,线程启动它们的过程中在状态计算机,更新它们的对象属性使用事件头中的主要进程和线程 ID 的这些活动。 在结束,进程和线程对象的聚合并汇总到使用不同的度量标准报表。

图像事件对应于获取加载和卸载到进程地址空间的图像 (也称为模块) 文件中。 有四种类型的图像的事件:加载,DCStart 和 DCEnd 中卸载。 杩欎簺浜嬩欢没有直接关联到 LoadLibrary 的呼叫但是。 如果 DLL 已经加载过程中,为同一个 DLL 随后 LoadLibrary 调用只是递增的模块的引用计数但将不映射模块再次。 像 DCStart 和 DCEnd 的进程和线程的事件类型,图像 DCStart 和 DCEnd 用于枚举的已运行的进程加载的模块。 图像事件允许加载模块的跟踪和进程内的地址的映射。 它们也是非常重要的映射 DPC ISR,系统调用的事件将在本系列的第 2 部分和更高节中讨论。 将图像事件有效负载包含信息,如模块地址基和大小,和二进制文件的名称加载 (或卸载)。 图像的事件也是必需的解码调用堆栈的。 在典型的状态机器构造中,图像事件触发更新的已加载的模块的列表为上述进程对象。

处理计数器事件时启用,将记录在进程终止记录其有效负载中有关该过程执行统计信息的几个属性通过该进程的生存期。 这些峰值内存大小、 峰值工作集大小、 峰值分页和非页面缓冲的池的使用和包含峰值页面文件使用。 这些事件表明进程仍然能够与内存有关的方式。 类似于进程的事件的事件集合的末尾的所有活动进程记录单独 rundown 的进程计数器事件。

图 2 NT 内核记录器启用标记为

>
logman query providers "Windows Kernel Trace"
Provider GUID
------------------------------------------------------------------------
Windows Kernel Trace {9E814AAD-3204-11D2-9A82-006008A86939}
Value Keyword Description
------------------------------------------------------------------------
0x0000000000000001 process Process creations/deletions
0x0000000000000002 thread Thread creations/deletions
0x0000000000000004 img Image load
0x0000000000000008 proccntr Process counters
0x0000000000000010 cswitch Context switches
0x0000000000000020 dpc Deferred procedure calls
0x0000000000000040 isr Interrupts
0x0000000000000080 syscall System calls
0x0000000000000100 disk Disk IO
0x0000000000000200 file File details
0x0000000000000400 diskinit Disk IO entry
0x0000000000000800 dispatcher Dispatcher operations
0x0000000000001000 pf Page faults
0x0000000000002000 hf Hard page faults
0x0000000000004000 virtalloc Virtual memory allocations
0x0000000000010000 net Network TCP/IP
0x0000000000020000 registry Registry details
0x0000000000100000 alpc ALPC
0x0000000000200000 splitio Split IO
0x0000000000800000 driver Driver delays
0x0000000001000000 profile Sample based profiling
0x0000000002000000 fileiocompletion File IO completion
0x0000000004000000 fileio File IO
The command completed successfully.

上下文切换,DPC 和 ISR 事件

上下文切换事件记录每次线程切换发生在 CPU 上,并可用于构造非常精确历史记录与已运行的线程和如何为多长时间。 它们非常频繁地发生,并且生成大量的数据。 每个的交换机涉及两个线程。 旧的线程将放弃其共享的执行时间,并手动执行新线程。 因此,上下文开关事件包含旧的和新的线程 ID 旧和新的线程优先级等待原因等待时间。 上下文切换可能发生各种由于原因包括在内核同步对象 (事件、 计时器、 信号量和等等),阻止 preemption 由优先级较高的线程、 量程到期和线程关联中的更改。 始终需要一定的上下文切换。 但是,过多的上下文切换的效率不高,因此使用同步基元的指示,可能会导致性能较差缩放。 启用上下文开关事件的调用堆栈上的线程获取切换出原因允许深入分析。

DPC 执行时延迟的过程调用 (DPC) 事件记录。 DPC 内核模式函数在提升的中断级别执行模式执行,它占先常规线程执行。 DPC 事件负载包括 DPC 进入时间和日常的地址。 中断服务例程 (ISR) 一个类似的机制,它运行较高级别执行比 DPC。 ISR 事件有 ISR 输入时间、 日常的地址、 ISR 向量和 ISR 返回值。 DPC 和 ISR 机制是在 Windows 驱动程序中的重要元素,因为它们通常用于处理硬件中断。 驱动程序和内核模式组件有一个权限使用 DPC 和 ISR,但强烈建议他们花一点时间,在这些高模式中为。 DPC 和 ISR 事件用于监视和验证各种驱动程序和内核模式组件的行为。 通过比较与区域信息中图像的事件例程地址,一个可以找到内核组件负责这些 DPC 和 ISR 事件。

状态机构造,组合上下文切换,DPC ISR 事件允许 CPU 使用率的一个非常准确的记帐。 通过保留将记录其当前的活动线程根据上下文切换,DPC ISR 事件的每个处理器的存储区设置一个可以监视--给定的任何时间戳--每个 CPU 已在做什么和它所执行的代码。 状态机模拟方法中, 后发生上下文切换,一个 CPU 的对象更新具有新的线程 ID,并因此是 CPU 使用率达开关的旧线程对象。 同样,DPC 和 ISR 事件是属性化到在相应的内核模式组件需要。

在煇浜涙儏鍐典笅如 IO、 内存或系统调用的事件与 ETW 不记录该进程或事件标头的主要是为了减少开销非常频繁的事件中的线程 ID。 这样的事件的标头中的线程和进程 ID 值显示为 0xFFFFFFFF (= 4294967295) 中。 如果与上面所述跟踪上下文切换,DPC ISR 事件,这些事件可以跟踪到线程或内核模式组件通过检查 CPU 对象当前正在运行的线程或 DPC/ISR.

内存事件

内存事件表示内存管理器 (分钟) 操作。 Windows 提供了页面错误事件、 硬页面错误事件和虚拟内存事件。 内存事件往往是尤其是在一个繁忙的系统上非常频繁。

页面错误时发生查找出页表项无效。 如果所请求的页需要从磁盘被引入,它被调用硬页错误 (非常昂贵的操作),并且所有其他类型被认为是软页面错误 (成本较低的操作)。 页面错误事件负载包含虚拟内存地址的页面错误发生了变化以及导致它的指令指针。 硬页错误需要磁盘访问发生,可能是第一个文件中的内容访问或访问被分页出来的内存块。 启用页面错误事件,将导致页面错误为记录类型硬页面错误硬页错误。 但是,硬错误通常对较大的影响对性能有,所以只供一个硬错误可以单独启用的一个单独的事件。 硬错误事件负载中具有如文件项,偏移量和线程 ID,与一个页面错误事件的更多数据。

虚拟内存事件由虚拟内存分配和可用虚拟内存的类型和对应于 MM 调用分配和释放虚拟内存区域组成。 其有效负载包含进程 ID、 基址、 请求的大小 API 调用中使用的标志。 虚拟内存事件新添加的 Windows 7,并可用于跟踪应用程序泄漏调用 VirtualAlloc 函数过多的虚拟内存使用情况。

内存事件的标头不包含导致特定活动的进程和线程的 ID。 页面错误事件负载中,但是,有导致该错误在线程的线程 ID。 这使页面错误的相关事件的线程和进程通过状态机。 虚拟内存事件负载中包含铏氭嫙鍐呭瓨操作执行的进程的 ID。 若要跟踪其线程进行 API 调用,需要上下文开关记帐、 上一节所述。

下期内容

Windows 7 功能数百个事件提供程序从各种组件。 在这两个部分文章系列的第一部分,我们已提供一些核心操作系统 ETW Windows 7 和我们使用许多年分析技术上可用的事件。 单个事件指示某些活动的核心操作系统,但如果组合通过区分上下文的分析方法,它们可以用于生成有意义的报告提供深入了解模式和资源使用情况的异常的。 在部件 2,我们计划介绍其他核心操作系统 ETW 事件,以及展示几个基本的记帐技术,在某些操作系统事件上存在简单的脚本介绍这些两个部分。 我们希望许多人将利用本文内容它将导致声音工程设计做法、 更大的软件质量和更好的用户体验的提升。

Dr. Insung Park 用于 Windows 检测和诊断平台团队的开发经理。 他已发布为十几个性能分析、 跟踪的请求,检测技术,和编程方法和支持的纸张。 insungp@microsoft.com 他的电子邮件地址。
Alex Bendetov 用于 Windows 检测和诊断平台团队的开发潜在顾客。 他适用于 Windows 事件跟踪和性能计数器技术。 他能到达在 alexbe@microsoft.com