http://sourceware.org/systemtap/
https://sourceware.org/systemtap/wiki
https://sourceware.org/systemtap/documentation.html
https://www.cnblogs.com/hazir/p/systemtap_introduction.html
https://vcpu.me/systemtap-skills/
http://www.redbooks.ibm.com/abstracts/redp4469.html
https://segmentfault.com/a/1190000010774974(推荐)
1、安装
Ubuntu
sudo apt-get install systemtap(不建议这么玩,Ubuntu自带的经常有问题)
centos
yum install systemtap systemtap-runtime
也可以通过源码进行安装,下载地址:https://sourceware.org/systemtap/ftp/releases/ 。解压然后进入根目录,执行如下命令:
tar -zxvf systemtap-4.1.tar.gz
cd systemtap-4.1/
./configure --prefix=/目录(期望安装的目录)
make
sudo make install
执行配置是可能遇到各种库找不到,缺啥补啥,常见的库是下面这些:
sudo apt-get install elfutils
sudo apt-get install libncurses5-dev
sudo apt-get install flex
sudo apt-get install bison
sudo apt-get install gettext
sudo apt-get install libdw-dev
sudo apt-get install g++
2、安装调试需要debug
首先由于Systemtap运行时需要内核的调试信息支撑,默认发行版的内核在配置时,这些调试开关是关闭的,所以为了Systemtap能够正常运行,我们首先要使内核开启运行调试信息功能。主要有两种方法:
方法一:下载并安装debuginfo安装包
由于发行版的内核默认无内核调试信息,所以我们还需要一个调试内核镜像,在http://ddebs.ubuntu.com/pool/main/l/linux/ 找到你的内核版本相对应的内核调试镜像(版本号包括后面的发布次数、硬件体系等都必须一致),
假设我的内核版本2.6.32-24,i386结构,那么我需要下载
linux-image-2.6.32-24-generic-dbgsym_2.6.32-24.42_i386.ddeb下载后安装
dpkg -i linux-image-2.6.32-24-generic-dbgsym_2.6.32-24.42_i386.ddeb
方法二:重新编译内核
参考:https://blog.csdn.net/linjiasen/article/details/89850357
1.git下载最新的内核源码
git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
或者更快的: git clone https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux.git
2 配置kernel
make memuconfig打开
General Setup -- ->
[*] Kernel->user space relay support (formerly relayfs)
[*] Kprobes
kernel hacking -- ->
[*]Kernel debugging
[*]Compile the kernel with debug info
[*]Debug Filesystem
然后查看.config下面debug信息是否打开
CONFIG_DEBUG_INFO
CONFIG_KPROBES
CONFIG_RELAY
CONFIG_DEBUG_FS
CONFIG_MODULES
CONFIG_MODULE_UNLOAD
CONFIG_UPROBES 或者CONFIG_UTRACE
3、测试是否安装成功
如果pass1-5都没有错误,说明systemtap安装成功了。
stap -ve 'probe kernel.function("_do_fork") { print("hello world\n") exit() }'
stap -ve 'probe begin { log("hello Systemtap!") exit() }'
stap -ve 'probe begin { log("hello Systemtap!") exit() }'
Pass 1: parsed user script and 476 library scripts using 116624virt/86344res/5540shr/81212data kb, in 280usr/40sys/331real ms.
Pass 2: analyzed script: 1 probe, 2 functions, 0 embeds, 0 globals using 118208virt/88052res/5676shr/82796data kb, in 10usr/0sys/9real ms.
Pass 3: using cached /root/.systemtap/cache/d0/stap_d06faf54f2557de2112cfd40af92ad47_1150.c
Pass 4: using cached /root/.systemtap/cache/d0/stap_d06faf54f2557de2112cfd40af92ad47_1150.ko
Pass 5: starting run.
WARNING: module version mismatch (#1 SMP Tue May 12 20:00:21 CST 2020 vs #1 SMP Tue May 12 16:41:02 CST 2020), release 5.3.0-rc7
hello Systemtap!
Pass 5: run completed in 0usr/10sys/455real ms.
上面打印的pass1-5就是对应SystemTap的处理流程有5个步骤:解析script文件(parse)、细化(elaborate)、script文件翻译成C语言代码(translate)、编译C语言代码(生成内核模块)(build)、加载内核模块(run)。
systemtap 的核心思想是定义一个事件(event),以及给出处理该事件的句柄(Handler)。当一个特定的事件发生时,内核运行该处理句柄,就像快速调用一个子函数一样,处理完之后恢复到内核原始状态。这里有两个概念:
- 事件(Event):systemtap 定义了很多种事件,例如进入或退出某个内核函数、定时器时间到、整个systemtap会话启动或退出等等。
- 句柄(Handler):就是一些脚本语句,描述了当事件发生时要完成的工作,通常是从事件的上下文提取数据,将它们存入内部变量中,或者打印出来。
evnet有很多种:进入和退出一个function,timer爆发,systemtap的开始和停止。
handler:脚本语言,当event发生时工作。
同步事件包括:
syscall.system_call
vfs.file_operation
kernel.function("function")
kernel.trace("tracepoint")
module("module").function("function")
异步事件包括:
begin
end
timer events
printf
Systemtap 工作原理是通过:将脚本语句翻译成C语句(Pass1 -3:parse-translate),编译成内核模块(Pass4:compile)。模块加载之后,将所有探测的事件以钩子的方式挂到内核上(load),当任何处理器上的某个事件发生时,相应钩子上句柄就会被执行(run)。最后,当systemtap会话结束之后,钩子从内核上取下,移除模块。整个过程用一个命令 stap
就可以完成。
4、使用
(1) stap
通常直接使用stap执行用SystemTap语法编写的脚本即可。
stap - systemtap script translator/driver
stap test.stp // .stp后缀的文件是用SystemTap语法编写的脚本
probe begin
{
print ("hello world\n")
exit ()
}
probe end
{
print ("Bye\n")
}
上面脚本保存成hello_world.stp,然后stap -v hello_world.stp执行,可以看到执行两条打印。这里begin和end就是event。
stap -v hello_world.stp
Pass 1: parsed user script and 476 library scripts using 116628virt/86416res/5608shr/81216data kb, in 260usr/20sys/280real ms.
Pass 2: analyzed script: 2 probes, 1 function, 0 embeds, 0 globals using 118212virt/88124res/5744shr/82800data kb, in 0usr/0sys/9real ms.
Pass 3: translated to C into "/tmp/stapcP149F/stap_95a8df27bac22dee8931f3f1827c6aeb_1046_src.c" using 118212virt/88124res/5744shr/82800data kb, in 0usr/0sys/0real ms.
Pass 4: compiled C into "stap_95a8df27bac22dee8931f3f1827c6aeb_1046.ko" in 2020usr/580sys/2963real ms.
Pass 5: starting run.
WARNING: module version mismatch (#1 SMP Tue May 12 20:00:21 CST 2020 vs #1 SMP Tue May 12 16:41:02 CST 2020), release 5.3.0-rc7
hello world
Bye
Pass 5: run completed in 0usr/30sys/539real ms.
(2) staprun
如果我们的输入不是.stp脚本,而是一个用stap生成的模块,那么就用staprun来执行。
staprun - systemtap runtime
staprun [OPTIONS] MODULE [MODULE-OPTIONS]