systemtap是内核开发者必需要掌握的一个工具,本文我将简单介绍一下此工具,后续将会有系列文章介绍systemtap的用法。html
假如如今有这么一个需求:须要获取正在运行的 Linux 系统的信息,如我想知道系统何时发生系统调用,发生的是什么系统调用等这些信息,有什么解决方案呢?linux
下面将会介绍systemtap的安装、systemtap的工做原理以及几个简单的示例。git
个人主机 Linux 发行版是32位 Ubuntu13.04,内核版本 3.8.0-30。因为 systemtap 运行须要内核的调试信息支撑,默认发行版的内核在配置时这些调试开关没有打开,因此安装完systemtap也是没法去探测内核信息的。 下面我以两种方式安装并运行 systemtap:ubuntu
编译内核以支持systemtap
咱们从新编译内核让其支持systemtap,首先你想让内核中有调试信息,编译内核时须要加上 -g 标志;其次,你还须要在配置内核时将 Kprobe 和 debugfs 开关打开。最终效果是,你能在内核 .config 文件中看到下面四个选项是设置的:markdown
CONFIG_DEBUG_INFO CONFIG_KPROBES CONFIG_DEBUG_FS CONFIG_RELAY
配置完以后,按照以前你编译内核的步骤编译便可。框架
获取systemtap源码
今后地址 https://sourceware.org/systemtap/ftp/releases下载已经发布的systemtap的源代码,截至目前(2013.9.17)最新版本为systemtap-2.3。下载完以后解压。 固然你还可使用 git 去克隆最新的版本(2.4),命令以下:函数
git clone git://sources.redhat.com/git/systemtap.git
编译安装systemtap
若是你下载的是最新版本的systemtap,那么你须要新版的 elfutils,能够从https://fedorahosted.org/releases/e/l/elfutils/ 下载elfutils-0.156 版本。下载以后解压缩到适合的目录(我放在~/Document/ 下),不须要安装,只要配置systemtap时指定其位置便可。 进入以前解压systemtap的目录,使用下面命令进行配置:工具
./configure --with-elfutils=~/Document/elfutils-0.156
以这里方法配置以后,你只须要再运行 make install 即完成systemtap的编译安装。若是须要卸载的话,运行 make uninstall。post
因为发行版的内核默认无内核调试信息,因此咱们还须要一个调试内核镜像,在http://ddebs.ubuntu.com/pool/main/l/linux/ 找到你的内核版本相对应的内核调试镜像(版本号包括后面的发布次数、硬件体系等都必须一致),如针对我上面的内核版本,就能够用以下命令下载安装内核调试镜像:性能
$ wget http://ddebs.ubuntu.com/pool/main/l/linux/linux-image-debug-3.8.0-30-generic_dbgsym_3.8.0-30.43_i386.ddeb $ sudo dpkg -i linux-image-debug-3.8.0-30-generic_dbgsym_3.8.0-30.43_i386.ddeb
通常这种方法下,你只须要使用apt在线安装systemtap便可:
$sudo apt-get install systemtap
固然方法二仅限于Ubuntu发行版,至于其余的发行版并不能照搬,网上也有不少相关的资料。
安装完systemtap以后,咱们须要测试一下systemtap是否能正确运行:
以root用户或者具备sudo权限的用户运行如下命令:
$stap -ve 'probe begin { log("hello systemtap!") exit() }'
若是安装正确,会获得以下相似的输出结果:
Pass 1: parsed user script and 96 library script(s) using 55100virt/26224res/2076shr/25172data kb, in 120usr/0sys/119real ms. Pass 2: analyzed script: 1 probe(s), 2 function(s), 0 embed(s), 0 global(s) using 55496virt/27016res/2172shr/25568data kb, in 0usr/0sys/4real ms. Pass 3: translated to C into "/tmp/stapYqNuF9/stap_e2d1c1c9962c809ee9477018c642b661_939_src.c" using 55624virt/27380res/2488shr/25696data kb, in 0usr/0sys/0real ms. Pass 4: compiled C into "stap_e2d1c1c9962c809ee9477018c642b661_939.ko" in 1230usr/160sys/1600real ms. Pass 5: starting run. hello systemtap! Pass 5: run completed in 0usr/10sys/332real ms.
建立systemtap脚本文件test2.stp:
#!/usr/bin/stap probe begin { log("begin to probe") } probe syscall.open { printf ("%s(%d) open (%s)\n", execname(), pid(), argstr) } probe timer.ms(4000) # after 4 seconds { exit () } probe end { log("end to probe") }
将该脚本添加可执行的权限 chmod +x test2.stp
,使用./test2.stp
运行该脚本,便可打印4s内全部open系统调用的信息,打印格式为:进程名(进程号)打开什么文件。 你们能够自行去测试,若是两个示例都能正确运行,基本上算是安装成功了!
systemtap 的核心思想是定义一个事件(event),以及给出处理该事件的句柄(Handler)。当一个特定的事件发生时,内核运行该处理句柄,就像快速调用一个子函数同样,处理完以后恢复到内核原始状态。这里有两个概念:
Systemtap 工做原理是经过将脚本语句翻译成C语句,编译成内核模块。模块加载以后,将全部探测的事件以钩子的方式挂到内核上,当任何处理器上的某个事件发生时,相应钩子上句柄就会被执行。最后,当systemtap会话结束以后,钩子从内核上取下,移除模块。整个过程用一个命令 stap
就能够完成。 上面只是简单的原理,更多背后的机理参考网上资料和相应的论文。 图 systemtap 处理流程