1 SystemTap简介
SystemTap是一个诊断Linux系统性能或功能问题的开源工具。它允许开发人员和系统管理员深入研究内核甚至用户空间应用程序的行为,以便发现错误状态、性能问题,或者仅仅为了解系统是如何工作的。它使得对运行时的Linux系统进行诊断调式变得更容易、更简单。通过使用SystemTap,可以很容易地总结和可视化与系统工作有关的信息,使您能够轻松地获得处理简单和复杂问题所需的信息
。
为了诊断系统问题或性能,开发者或调试人员只需要写一些脚本,而且SystemTap本身也提供了很多脚本,称为"tapset"方便开发。通过SystemTap提供的命令行接口就可以对正在运行的内核进行诊断调试,以前需要的修改或插入调试代码、重新编译内核、安装内核和重启动等这些琐碎的工作完全消除
当前该项目的主要开发人员为来自Red Hat, IBM, Intel和Hitachi的工程师。其中Redhat主要负责脚本转换/翻译器和运行时库,IBM负责kprobe和relayfs,Intel负责转换器安全检查以及performance monitor tapset。
2 SystemTap架构
2.1 Kprobes简介
SystemTap用于检查运行的内核的两种方法是 Kprobe和返回探针(return probes)。
Kprobes从 2.6.9 版本开始就添加到主流的 Linux 内核中,并且为探测内核提供一般性服务,最重要的两种服务是 Kprobe 和 Kretprobe。
Kprobe是一个通用钩子,可以插入内核代码中的几乎任何地方。为了允许它探测一条指令,该指令的第一个字节被替换为所使用架构的断点指令。当命中这个断点时,Kprobe接管并执行对应的探针处理程序代码,执行完成之后,接着执行原始的指令(从断点开始)。
Kretprobe(返回探针)有所不同,它操作调用函数的返回结果。因为一个函数可能有多个返回点,它实际使用一种称为 trampoline(蹦床) 的简单技术。它向函数条目添加一小段代码,而不是检查函数中的每个返回点。这段代码使用 trampoline 地址替换堆栈上的返回地址。当函数退出时,它返回到trampoline地址,而不是最初设置它返回的位置,并调用探测的处理程序代码。然后从 Kretprobe 返回到实际的调用方。Kretprobe的工作原理如图2-1所示。
2.2 SystemTap流程
SystemTap的基本流程主要涉及到 3 个交互实用程序stap、staprun和stapio,以及如下5个阶段:
1. 解析阶段:将stap脚本解析成语法解析树,会执行预处理,以及语义和语法正确性检查。
2. 细化阶段:解析脚本中的符合和引用,导入脚本中引用的脚本库tapsets(目录一般为/usr/share/SystemTap/tapset/)和内核调试信息。
3. 转化阶段:结合细化阶段的输出,将解析树转换成 C 源代码。
4. 构建阶段:将C代码编译成可以在内核中动态加载和执行的内核模块。
5. 执行阶段:staprun 和 stapio负责将模块安装到内核中并将输出发送到 stdout。如果在shell中按组合键 Ctrl-C或脚本退出,将执行清除进程,这将导致卸载模块并退出所有相关的实用程序。SystemTa在加载这个模块后,会开启脚本中的探测点。这个功能由systemtap-runtime包中的staprun提供;当某个事件发生时,对应的处理句柄(handler)就会执行;当SystemTap会话终止时,探测就会停止,对应的内核模块也会卸载。
SystemTap的流程如图2-2和图2-3所示。
SystemTap 的一个有趣特性是缓存脚本转换的能力。如果安装后的脚本没有更改,您可以使用现有的模块,而不是重新构建模块。图2-4显示了user-space和kernel-space 元素以及基于 stap的转换流程。
2.3 SystemTap原理
SystemTap的核心思想是定义一个事件(event),以及给出处理该事件的句柄(Handler)。当一个特定的事件发生时,内核运行该处理句柄,就像快速调用一个子函数一样,处理完之后恢复到内核原始状态。这里有两个概念:
-
事件(Event):SystemTap定义了很多种事件,例如进入或退出某个内核函数、定时器时间到、整个SystemTap会话启动或退出等等。
-
句柄(Handler):就是一些脚本语句,描述了当事件发生时要完成的工作,通常是从事件的上下文提取数据,将它们存入内部变量中,或者打印出来。
SystemTap工作原理是通过将脚本语句翻译成C语句,编译成内核模块。模块加载之后,将所有探测的事件以钩子的方式挂到内核上,当任何处理器上的某个事件发生时,相应钩子上句柄就会被执行。最后,当SystemTap会话结束之后,钩子从内核上取下,移除模块。整个过程用一个命令 stap 就可以完成。
SystemTap使用了类似于awk和C语言的脚本语言(类似于Dtrace的D语言)。它只使用了三种数据类型:整数(integers)、字符串(strings)和关联数组(associative Arrays)。它有完整的控制结构,包括块(blocks)、条件(conditionals)、循环(loops)和函数(functions)。语句分割符;是可选的,变量不需要声明类型,它们是根据上下文自动推测和检查的,它使用了kprobe提供的接口来实现探测,对于每一个探测,需要定