安装SystemTap(ubuntu10.10)
简便的安装方式通过下面命令直接下载并安装在系统里:
# sudo apt-get install systemtap
也可以去http://sourceware.org/systemtap/getinvolved.html
下载各种版本的systemtap。
具体的安装说明可以参考官网上的指导:
http://sourceware.org/git/?p=systemtap.git;a=blob_plain;f=README;hb=HEAD
我参考的是一篇技术博客:
http://www.ningoo.net/html/2010/use_systemtap_on_ubuntu.html
Ubuntu Desktop默认没有安装kernel debug info的包,systemtap无法追踪内核信息。查看内核版本:
# uname –r
在http://archive.ubuntu.com/ubuntu/pool/main/l/linux/?C=S;O=A下载对应的kernel debug info包
在网上下载不到linux-image-2.6.35-22-generic-dbgsym_2.6.35-22.35_i386.ddeb这个调试包,只用2.6.32和2.6.38版本的,所以我在vbox虚拟机上安装了ubuntu10.04(下载地址:http://www.ubuntu.com/download/ubuntu/download),其内核版本是:2.6.32-33-generic
在http://ddebs.ubuntu.com/pool/main/l/linux/地址可以下载到对应的kernel debug info
注意下载调试包的时候注意后面的小号也要一致!用# uname –a来查看小号!
根据systemtap的语法规则,我尝试了一些命令的编写,可以编写个脚本对文件进行监测:
# sudo stap ‘probegeneric.fop.open { if(filename == "secrets") printf("%s isopening my file: %s\n", execname(), filename) }’
先运行上面监测命令,当打开secrets文件时,终端上将显示对文件的操作!
# sudo stap –ve ‘probebegin { printf("a \\ b "); for (c = 40; c < 48; c++) printf("%d ", c); printf("\12"); for (l = 0; l < 71; l++)printf("-"); printf("\12"); for (r = 30; r < 38; r++)for (t = 0; t < 2; t++) { printf("%d ", r); for (c = 40; c <48; c++) printf("\033[%d;%d%s %s \033[0;0m", r, c, !t ? "m": ";1m", !t ? "Normal" : "Bold ");printf("\12"); } exit(); }’
SystemTap不仅仅是一个简单的调试工具,强大的脚本语言能力让它同样能做一些有趣的事情,下面这个例子就可以对输出的字符进行美化:
在进行性能分析的时候,我们常常需要知道那些函数调用次数最多,才能有的放矢地展开分析。下面这个简单的例子可以打印出在过去的5秒钟里调用次数最多的那些系统调用。
# sudo stap -ve'global syscalls function print_top () { cnt=0 log("SYSCALL\t\t\t\tCOUNT") foreach ([name] in syscalls-) {printf("%-20s\t\t%5d\n",name, syscalls[name]) if (cnt++ == 10) break} printf("--------------------------------------\n") delete syscalls} probe syscall.* { syscalls[probefunc()]++ } probe timer.ms(5000) { print_top() }'
小结:
在运行几个脚本后,我逐渐发现systemtap之所以受linux程序员的欢迎,是因为当你需要打印出某个函数的参数时,不再需要在内核源码中重新插入一行输出代码,然后重新编译内核才能看到想要输出的结果。有了systemtap可以通过编写一些脚本文件(.stp)*的收集调试信息和性能数据,无需修改内核代码和漫长的内核代码编译了。
经过几个测试,开始了解了systemtap的基本工作原理,下面简单说下5个pass的作用:
Pass 1 - parse:这个阶段主要是检查输入脚本是否存在语法错误,例如大括号是否匹配,变量定义是否规范等
Pass 2 - elaborate:这个阶段主要是对输入脚本中定义的探测点或者用到的函数展开,不但需要综合SystemTap的预定义脚本库,还需要分析内核或者内核模块的调试信息
Pass 3 -translate: 在这个阶段,将展开后的脚本转换成C文件。前三个阶段的功能类似于编译器,将.stp文件编译成为完整的.c文件,因此又被合起来称为转换器(translator)
Pass 4 - build:在这个阶段,将C源文件编译成内核模块,在这过程中还会用到SystemTap的运行时库函数。
Pass 5 - run:这个阶段,将编译好的内核模块插入内核,开始进行数据收集和传输。