一、简介
SystemTap是一个诊断Linux系统性能或功能问题的开源软件。它使得对运行时的Linux系统进行诊断调式变得更容易、更简单。有了它,开发者或调试人员不再需要重编译、安装新内核、重启动等烦人的步骤。
为了诊断系统问题或性能,开发者或调试人员只需要写一些脚本,然后通过SystemTap提供的命令行接口就可以对正在运行的内核进行诊断调试,以前需要的修改或插入调试代码、重新编译内核、安装内核和重启动等这些琐碎的工作完全消除。目前该工具并不支持对用户态应用的诊断调试,但是它们在以后会被添加进去。当前该项目的主要开发人员为来自Red Hat, IBM, Intel和Hitachi的工程师。其中Redhat主要负责脚本转换/翻译器和运行时库,IBM负责kprobe和relayfs,Intel负责转换器安全检查以及performance monitor tapset。
二、Systemtap原理
Systemtap使用了类似于awk和C语言的脚本语言(类似于Dtrace的D语言),它只使用了三种数据类型,整数(integers)、字符串(strings)以及关联数组(associative Arrays),它有完整的控制结构,包括块(blocks)、条件(conditionals)、循环(loops)和函数(functions)。语句分割符;是可选的,变量不需要声明类型,它们是根据上下文自动推测和检查的,它使用了kprobe提供的接口来实现探测,对于每一个探测,需要定义探测点以及相应的处理函数,探测点就是指kprobe中被探测的函数或指令地址(也被称为内核事件)的),但在Systemtap中,用户可以指定原文件,原代码的某一行,或者一个异步事件,如周期性的定时器,探测点使用了层次化的命名方式,探测点处理函数能够立刻输出数据,与printk很类似,它也能查看内核数据。脚本然后被一个翻译器转换成C代码并编译成一个内核模块。探测点根据内核的DWARF调试信息映射到内核的虚地址(因此Systemtap要求用户必须准备好可用的内核调试信息),所有的脚本内容在转换时进行严格的检查,并且在运行时也要检查(如无限循环、内存使用、递归和无效指针等),因此有好的安全性,不会影响正在运行的系统(这对生产系统是非常重要的)。 Systemtap包含了一个黑名单,其中列出的函数不能被Systemtap探测,因为它们会导致无限探测循环、锁重入等问题。
下图直观地给出了Systemtap的工作原理:
图 1. Systemtap工作原理
Systemtap脚本文件是.stp后缀的文件,使用的脚本语言是前面讲到的Systemtap自己定义的脚本语言,一个Systemtap脚本描述了将要探测的探测点以及定义了相关联的处理函数,每一个探测点对应于一个内核函数或事件或函数内部的某一位置。被关联的处理函数将在内核执行到对应的探测点时被执行。
tapsets是一个脚本库,包含了许多tapset,每一个tapset一般为某一内核子系统或特定的功能块预定义了一套探测点、辅助函数或全局变量供用户脚本或其它的tapset引用,它定义的一些数据能够被每一个探测点处理函数或脚本使用,这些数据通常通过使用处理函数语句块(HSB Handler Statement Block)来出口,HSB语句块中的变量就是被出口的数据。tapset一般由该内核子系统的开发者或对子系统非常了解的开发者编写,既使用了脚本语言,也使用了C语言,并且它已经被测试和验证,可以安全使用。tapsets属于Systemtap发行包的一部分。
Systemtap实现了一个脚本转换器/翻译器,当用户执行一个Systemtap脚本时,Systemtap将首先对它进行分析和一些安全检查,如果它引用了Systemtap预定义的脚本库提供的函数,Systemtap也将读取脚本库得到相应的代码,对于一些内核变量或符号的引用,它必须根据内核调试信息来解析到相应的地址。然后,它被转换成C代码,在这个转换中,Systemtap将根据需要增加必要的锁和安全检查代码。探测点之间共享的变量将被转换成恰当的静态声明并有锁保护,每组本地变量被转换到一个合成的调用帧结构中以避免消耗内核的栈空间。关联到探测点的处理函数被封装成一个接口函数,那调用恰当的kprobe接口函数来注册该探测点。
产生的C代码包含了一些对运行时tapset的引用,运行时tapset库提供了许多Systemtap接口函数,如通用的查询表、受限内存管理、启动、关闭、I/O操作以及其它一些函数。生成的C代码编译链接之后生成一个可加载的内核模块。为了快速得到运行结果,Systemtap使用了relayfs,当加载生成的内核模块后,该模块的初始化函数初始化自身,然后调用kprobe接口函数注册脚本中定义的探测点。当内核运行到注册的探测点时,相应的处理函数被调用,用户在处理函数中的输出语句将调用relayfs接口函数输出结果数据,用户在处理函数也可以调用一些内核的性能测量函数。当用户主动停止或脚本设定的条件满足时,模块将调用退出函数卸载已经注册的探测点并做一些清理处理就卸载模块自身。
Systemtap在运行时启动了一个进程,它专门负责通过relayfs读去模块的输出数据并即时地输出给用户。
三、SystemTap与DTrace比较
项目方面:
图 2. Systemtap与DTrace比较:项目方面
使用的语言:
图 3. Systemtap与DTrace比较:使用的语言
探测能力:
图 4. Systemtap与DTrace比较:探测能力
安全性:
图 5. Systemtap与DTrace比较:安全性
图形用户界面:
图 6. Systemtap与DTrace比较:图形用户界面
四、Systemtap的安装
运行Systemtap的前提条件是:
# yum install kernel-devel
# yum --enablerepo=core-debuginfo --enablerepo=updates-debuginfo \
install kernel-debuginfo
# yum install systemtap
然后运行下面命令可以验证是否成功。
# stap -ve 'probe begin { log("hello world") exit () }'
# stap -c df -e 'probe syscall.* { if (target()==pid()) log(name." ".argstr) }'
如果您想安装最新的Systemtap,您可以自己用源码包来构建,其步骤是:
1.确保elfutils支持libdwlf
如果您的elfutils并没有libdwlf,您需要下载它。
Systemtap能自动build它,因此对于这种情况,您只需下载最新的elfutils
ftp://sources.redhat.com/pub/systemtap/elfutils/elfutils-NNNN.tar.gz
ftp://sources.redhat.com/pub/systemtap/elfutils/elfutils-portability.patch
,解压elfutils-NNNN.tar.gz并打上补丁elfutils-portability.patch.具体命令如下:
# cd /home/yangyi
# wget ftp://sources.redhat.com/pub/systemtap/elfutils/elfutils-NNNN.tar.gz
# wget ftp://sources.redhat.com/pub/systemtap/elfutils/elfutils-portability.patch
# tar zxvf elfutils-NNNN.tar.gz
# cd elfutils-NNNN
# patch p0 ../ elfutils-portability.patch
2. 下载Systemtap源码包并解压
# cd /home/yangyi
# wget ftp://sources.redhat.com/pub/systemtap/snapshots/systemtap-YYYYMMDD.tar.bz2
# tar -jxvf systemtap-YYYYMMDD.tar.bz2
# cd systemtap-YYYYMMNN/src
或
# cvs -d :pserver:anoncvs@sources.redhat.com:/cvs/systemtap login
注:密码是anoncvs
# cvs -d :pserver:anoncvs@sources.redhat.com:/cvs/systemtap co src
# cd src
3.安装
# ./configure [--with-elfutils=/home/yangyi/elfutils-NNNN] [other autoconf options]
# make all check
# make install
注意,选项—with-elfutils带的参数是elfutils的源码包的路径,如果您已经安装了最新的elfutils,这个选项是不必要的.
对于其它Linux发行,没有便捷的安装方式可利用,您必须自己构建内核并设置Systemtap要求的前提条件。有时,您可能想使用最新的内核,您也可以使用这种方式来做。
要想编译一个支持Systemtap的内核,您必须配置这些内核选项:
Kernel hacking --->
SystemTap是一个诊断Linux系统性能或功能问题的开源软件。它使得对运行时的Linux系统进行诊断调式变得更容易、更简单。有了它,开发者或调试人员不再需要重编译、安装新内核、重启动等烦人的步骤。
为了诊断系统问题或性能,开发者或调试人员只需要写一些脚本,然后通过SystemTap提供的命令行接口就可以对正在运行的内核进行诊断调试,以前需要的修改或插入调试代码、重新编译内核、安装内核和重启动等这些琐碎的工作完全消除。目前该工具并不支持对用户态应用的诊断调试,但是它们在以后会被添加进去。当前该项目的主要开发人员为来自Red Hat, IBM, Intel和Hitachi的工程师。其中Redhat主要负责脚本转换/翻译器和运行时库,IBM负责kprobe和relayfs,Intel负责转换器安全检查以及performance monitor tapset。
二、Systemtap原理
Systemtap使用了类似于awk和C语言的脚本语言(类似于Dtrace的D语言),它只使用了三种数据类型,整数(integers)、字符串(strings)以及关联数组(associative Arrays),它有完整的控制结构,包括块(blocks)、条件(conditionals)、循环(loops)和函数(functions)。语句分割符;是可选的,变量不需要声明类型,它们是根据上下文自动推测和检查的,它使用了kprobe提供的接口来实现探测,对于每一个探测,需要定义探测点以及相应的处理函数,探测点就是指kprobe中被探测的函数或指令地址(也被称为内核事件)的),但在Systemtap中,用户可以指定原文件,原代码的某一行,或者一个异步事件,如周期性的定时器,探测点使用了层次化的命名方式,探测点处理函数能够立刻输出数据,与printk很类似,它也能查看内核数据。脚本然后被一个翻译器转换成C代码并编译成一个内核模块。探测点根据内核的DWARF调试信息映射到内核的虚地址(因此Systemtap要求用户必须准备好可用的内核调试信息),所有的脚本内容在转换时进行严格的检查,并且在运行时也要检查(如无限循环、内存使用、递归和无效指针等),因此有好的安全性,不会影响正在运行的系统(这对生产系统是非常重要的)。 Systemtap包含了一个黑名单,其中列出的函数不能被Systemtap探测,因为它们会导致无限探测循环、锁重入等问题。
下图直观地给出了Systemtap的工作原理:
图 1. Systemtap工作原理
Systemtap脚本文件是.stp后缀的文件,使用的脚本语言是前面讲到的Systemtap自己定义的脚本语言,一个Systemtap脚本描述了将要探测的探测点以及定义了相关联的处理函数,每一个探测点对应于一个内核函数或事件或函数内部的某一位置。被关联的处理函数将在内核执行到对应的探测点时被执行。
tapsets是一个脚本库,包含了许多tapset,每一个tapset一般为某一内核子系统或特定的功能块预定义了一套探测点、辅助函数或全局变量供用户脚本或其它的tapset引用,它定义的一些数据能够被每一个探测点处理函数或脚本使用,这些数据通常通过使用处理函数语句块(HSB Handler Statement Block)来出口,HSB语句块中的变量就是被出口的数据。tapset一般由该内核子系统的开发者或对子系统非常了解的开发者编写,既使用了脚本语言,也使用了C语言,并且它已经被测试和验证,可以安全使用。tapsets属于Systemtap发行包的一部分。
Systemtap实现了一个脚本转换器/翻译器,当用户执行一个Systemtap脚本时,Systemtap将首先对它进行分析和一些安全检查,如果它引用了Systemtap预定义的脚本库提供的函数,Systemtap也将读取脚本库得到相应的代码,对于一些内核变量或符号的引用,它必须根据内核调试信息来解析到相应的地址。然后,它被转换成C代码,在这个转换中,Systemtap将根据需要增加必要的锁和安全检查代码。探测点之间共享的变量将被转换成恰当的静态声明并有锁保护,每组本地变量被转换到一个合成的调用帧结构中以避免消耗内核的栈空间。关联到探测点的处理函数被封装成一个接口函数,那调用恰当的kprobe接口函数来注册该探测点。
产生的C代码包含了一些对运行时tapset的引用,运行时tapset库提供了许多Systemtap接口函数,如通用的查询表、受限内存管理、启动、关闭、I/O操作以及其它一些函数。生成的C代码编译链接之后生成一个可加载的内核模块。为了快速得到运行结果,Systemtap使用了relayfs,当加载生成的内核模块后,该模块的初始化函数初始化自身,然后调用kprobe接口函数注册脚本中定义的探测点。当内核运行到注册的探测点时,相应的处理函数被调用,用户在处理函数中的输出语句将调用relayfs接口函数输出结果数据,用户在处理函数也可以调用一些内核的性能测量函数。当用户主动停止或脚本设定的条件满足时,模块将调用退出函数卸载已经注册的探测点并做一些清理处理就卸载模块自身。
Systemtap在运行时启动了一个进程,它专门负责通过relayfs读去模块的输出数据并即时地输出给用户。
三、SystemTap与DTrace比较
项目方面:
图 2. Systemtap与DTrace比较:项目方面
使用的语言:
图 3. Systemtap与DTrace比较:使用的语言
探测能力:
图 4. Systemtap与DTrace比较:探测能力
安全性:
图 5. Systemtap与DTrace比较:安全性
图形用户界面:
图 6. Systemtap与DTrace比较:图形用户界面
四、Systemtap的安装
运行Systemtap的前提条件是:
- 内核支持并配置了kprobe(2.6.11和以上)
- 内核模块编译环境(即编译内核模块所需的内核头文件以及模块配置信息,对于Fedora core或Redhat指kernel-devel或kernel-smp-devel RPM包)
- 内核调试信息(对于Fedora core或Redhat指kernel-debuginfo RPM包)
- C编译环境(即libc库头文件和编译工具链)
- 有libdwfl的elfutils(只有支持libwdfl的elfutils,systemtap才能正常工作,如果您的系统的elfutils较旧,您必须下载elfutils源码包来编译,systemtap能够和elfutils一块编译)
- root权限(为了运行Systemtap,您必须具有root权限)
# yum install kernel-devel
# yum --enablerepo=core-debuginfo --enablerepo=updates-debuginfo \
install kernel-debuginfo
# yum install systemtap
然后运行下面命令可以验证是否成功。
# stap -ve 'probe begin { log("hello world") exit () }'
# stap -c df -e 'probe syscall.* { if (target()==pid()) log(name." ".argstr) }'
如果您想安装最新的Systemtap,您可以自己用源码包来构建,其步骤是:
1.确保elfutils支持libdwlf
如果您的elfutils并没有libdwlf,您需要下载它。
Systemtap能自动build它,因此对于这种情况,您只需下载最新的elfutils
ftp://sources.redhat.com/pub/systemtap/elfutils/elfutils-NNNN.tar.gz
ftp://sources.redhat.com/pub/systemtap/elfutils/elfutils-portability.patch
,解压elfutils-NNNN.tar.gz并打上补丁elfutils-portability.patch.具体命令如下:
# cd /home/yangyi
# wget ftp://sources.redhat.com/pub/systemtap/elfutils/elfutils-NNNN.tar.gz
# wget ftp://sources.redhat.com/pub/systemtap/elfutils/elfutils-portability.patch
# tar zxvf elfutils-NNNN.tar.gz
# cd elfutils-NNNN
# patch p0 ../ elfutils-portability.patch
2. 下载Systemtap源码包并解压
# cd /home/yangyi
# wget ftp://sources.redhat.com/pub/systemtap/snapshots/systemtap-YYYYMMDD.tar.bz2
# tar -jxvf systemtap-YYYYMMDD.tar.bz2
# cd systemtap-YYYYMMNN/src
或
# cvs -d :pserver:anoncvs@sources.redhat.com:/cvs/systemtap login
注:密码是anoncvs
# cvs -d :pserver:anoncvs@sources.redhat.com:/cvs/systemtap co src
# cd src
3.安装
# ./configure [--with-elfutils=/home/yangyi/elfutils-NNNN] [other autoconf options]
# make all check
# make install
注意,选项—with-elfutils带的参数是elfutils的源码包的路径,如果您已经安装了最新的elfutils,这个选项是不必要的.
对于其它Linux发行,没有便捷的安装方式可利用,您必须自己构建内核并设置Systemtap要求的前提条件。有时,您可能想使用最新的内核,您也可以使用这种方式来做。
要想编译一个支持Systemtap的内核,您必须配置这些内核选项:
Kernel hacking --->
|