微内核(procnto-instr)的插装版本配备了复杂的跟踪和分析机制,可以让实时监视系统的执行。procnto-instr模块在单CPU和SMP系统上工作。
procnto-instr模块使用的开销非常小,并且提供了非常好的性能——它的速度通常是插装内核的98%(当它不进行日志记录时)。插装的内核中额外的代码量(在x86系统上约为30kb)对于增加这个有用工具的能力和灵活性来说是一个相对较小的代价。根据最终系统的内存占用要求,可以选择使用这个特殊的内核作为开发/原型工具或最终产品中的实际内核。
插装的模块是非入侵模块——不必修改程序的源代码来监视程序如何与内核交互。可以根据需要在内核和系统中任何正在运行的线程或进程之间跟踪尽可能多或尽可能少的交互(例如,内核调用、状态更改和其他系统活动)。甚至可以监视中断。在这种情况下,所有这些活动都称为事件。
以下是内核检测涉及的基本任务:
1.插装的微内核(procnto-instr)由于各种系统活动而发出跟踪事件。这些事件被自动复制到一组缓冲区中,这些缓冲区被分组到一个循环链表中。
2.一旦缓冲区内的事件数量达到最高点,内核就会通知数据捕获实用程序。
3.数据捕获实用程序将跟踪事件从缓冲区写入输出设备(例如,串行端口、事件文件等)。
4.数据解释工具解释事件并将数据呈现给用户。
图30:内核检测过程
考虑到活动系统中发生的大量活动,内核发出的事件数量可能会非常多(就数据量、处理需求和存储所需的资源而言)。但是可以轻松地控制发出的数据量。具体来说,可以如下:
•控制触发事件释放的初始条件
•应用预定义的内核过滤器来动态控制释放
•实现自己的事件处理程序,以便进行更多的过滤。
数据捕获实用程序tracelogger收集数据之后,就可以对其进行分析。可以在收集相关事件之后实时或离线分析数据。IDE中的系统分析工具以图形的方式显示这些数据,因此可以“看到”系统中正在发生的事情。
除了应用各种过滤器来控制事件流之外,还可以指定内核用来发出事件的两种模式之一:
快速模式:只发出关于事件的最相关的信息(例如,只有两个内核调用参数)。
广播模式:为同一事件生成更多信息(例如,所有内核调用参数)。
这里的权衡是速度与知识之间的权衡:快速模式提供的数据更少,而广播模式为每个事件打包了更多的信息。无论哪种方式,都可以轻松地调优系统,因为这些模式在每个事件的基础上工作。作为快速和广播发射模式区别的一个例子,看看MsgSendv()调用条目可能看到的信息:
内核可以将所有跟踪事件保存在内部循环缓冲区中,而不是总是向外部设备发出事件。
当满足一定的触发条件时,这个缓冲区可以按编程方式按需转储到外部设备,这使它成为一种非常强大的工具,用于识别在特定的运行时条件下突然出现的难以捉摸的bug。
事件的数据包括高精度时间戳以及生成事件的CPU的ID号。这些信息有助于轻松诊断难以在多处理器系统上出现的困难时序问题。
事件格式还包括CPU平台(如x86、ARM等)和endian类型,便于远程分析(实时或离线)。使用数据解释器,可以以各种方式查看数据输出,例如:
•基于时间戳的整个系统的线性表示
•只有活动线程/进程的“运行”视图
•每个进程/线程的基于状态的事件视图。
数据解释器的线性输出可能是这样的:
为了帮助调整对事件数据流的解释,提供了一个库(traceparser),这样就可以编写自己的自定义事件解释器。
系统分析工具包(SAT)的IDE模块可以作为综合仪表控制和后处理可视化工具。
在IDE中,开发人员可以配置所有跟踪事件和模式,然后将日志文件自动传输到远程系统进行分析。作为一个可视化工具,IDE提供了一组丰富的事件和流程过滤器,旨在帮助开发人员快速删除大量的事件集,以便只查看那些感兴趣的事件。
图31:IDE可视化系统活动
虽然插装的内核为插装和监视进程、线程和系统状态提供了一种优秀的、不引人注目的方法,但是也可以让应用程序主动地影响事件收集过程。使用TraceEvent()库调用,应用程序本身可以将定制的事件注入跟踪流。当构建大型、紧密耦合的多组件系统时,这种设备特别有用。
例如,下面的简单调用会将eventcode的整数值,first和second注入事件流:
还可以向事件流注入一个字符串(例如,“My Event”),如下面的代码所示:
由traceprinter数据解释器收集的输出将如下所示: