systemtap概述及实例

  • Post author:
  • Post category:其他


systemtap对用户级和内核级代码提供了静态和动态跟踪的功能。Systemtap采用其他的内核框架做源:静态探针用tracepoints、动态探针用kprobes、用户级别的探针用uprobes。这些源也为perf、LTTng所用。

由于 systemtap 运行需要内核的调试信息支撑,默认发行版的内核在配置时这些调试开关没有打开,所以安装完systemtap也是无法去探测内核信息的。

Systemtap 工作原理是通过将脚本语句翻译成C语句,编译成内核模块。模块加载之后,将所有探测的事件以钩子的方式挂到内核上,当任何处理器上的某个事件发生时,相应钩子上句柄就会被执行。最后,当systemtap会话结束之后,钩子从内核上取下,移除模块。

工作原理如下图:

c1fd7adcdbe49bdef39239640b3d763cf487ac0c

安装

安装分为两部分:一部分为是systemtap工具本身,另一部分是内核调试信息。

在ubuntu中使用apt-get install systemtap命令进行安装。

因为systemtap需要内核信息来防止指令,所以需要安装debug info,先通过命令uname -r查看内核版本,然后安装linux-image-[uname –r]-

dbgsym

Ubuntu参考:


https://wiki.ubuntu.com/DebuggingProgramCrash#Built-in_debug_symbol_packages_.28.2A-dbg.29

其中4.4.0-63的下载链接如下:

http://launchpadlibrarian.net/304789714/linux-image-4.4.0-63-generic-dbgsym_4.4.0-63.84_amd64.ddeb

4.14.0下载地址:

https://launchpad.net/ubuntu/artful/amd64/linux-image-4.13.0-43-generic-dbgsym/4.13.0-43.48

ubuntu16的其他相关下载地址:

https://packages.ubuntu.com/zh-cn/xenial/amd64/linux-image-4.13.0-43-generic/download

或者直接运行stap-prep命令来进行安装。

也可以使用一个老外写的脚来下载,如下:


wget



http://www.domaigne.com/download/tools/get-dbgsym


chmod +x get-dbgsym


sudo ./get-dbgsy

另外,实例脚本位于:/usr/share/systemtap/tapset中。

红帽手动配置debuginfo

编译完内核后,执行如下命令:


#ln -s /kernel/linux-4.15.15/vmlinux /boot/vmlinux-`uname -r`


#ln -s /lib/modules/`uname -r` /usr/lib/debug/lib/modules/`uname -r`


#cd /usr/lib/debug/lib/modules/`uname -r`


然后执行如下脚本:


for file in `find -name ‘*.ko’ -print`


do


buildid=`eu-readelf -n $file| grep Build.ID: | awk ‘{print $3}’`


dir=`echo $buildid | cut -c1-2`


fn=`echo $buildid | cut -c3-`


mkdir -p /usr/lib/debug/.build-id/$dir


ln -s $file /usr/lib/debug/.build-id/$dir/$fn


ln -s $file /usr/lib/debug/.build-id/$dir/${fn}.debug


done

探针

探针的定义由句号分隔。示例如下:

begin:程序开始

end:程序开始

syscall.read: 系统调用read()的开始

syscall.read.return:系统调用read()的结束。

kernel.function(“sys_read”):内核函数sys_read()的开始

kernel.function(“sys_read”).return:内核函数sys_read的结束

socket.send:发送包

timer.ms(100):每100ms触发一次探针

timer.profile:按内核时钟频率对所有的CPU都触发的探针,用于采样/剖析。

process(“a.out”).statement(


*@main.c:100


): 跟踪目标进程,可执行文件a.out,main.c的100行。

tapset

一组相关的探针被称为tapset。

syscall:系统调用

ioblock:块设备接口和IO调度器

scheduler:内核CPU调度器事件

memory:进程和虚拟内存使用

scsi:SCSI目标事件

networking:网络设备事件

tcp:TCP协议事件

socket:套接字事件

此外systemtap还提供了许多action和内置变量,例如execname()获取进程名,pid()获取当前进程ID,print_backtrace()打印内核栈的回溯信息。

开销

systemtap 在编译阶段会消耗CPU资源。也可以在不同的系统上编译systemtap程序,然后将缓存结果传输给目标系统。

实战

执行如下代码:


# stap -ve ‘probe begin {log(“hello!”) exit()}’

实例代码

创建open.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”)


}

使用

#stap open.stp 开始执行。

这个脚本会在系统中调用open时候,将调用者的执行名字和进程号给打印出来,只要有人调用open就会打印,无所遁形。Systemtap提供了很多可以被printf函数调用的函数,除了execname(),pid()外,还有tid()等等。

常用的有:tid(),uid(),cpu(),gettimeofday_s(),ctime(),pp(),thread_indent(),

因为发行版本本身不包含debuginfo,所以在使用时候难免有些阻碍。

相比oprofile,systemtap适合做跟踪,而oprofile适合做性能诊断。

参考

官方源码:

https://sourceware.org/systemtap/documentation.html

《SystemTap_Begginers_Guide.pdf》


https://sourceware.org/systemtap/archpaper.pdf

官方实例:

https://sourceware.org/systemtap/examples/