使用systemtap调试linux内核

安装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调试linux内核

使用systemtap调试linux内核

根据systemtap的语法规则,我尝试了一些命令的编写,可以编写个脚本对文件进行监测:

# sudo stap ‘probegeneric.fop.open { if(filename == "secrets") printf("%s isopening my file: %s\n", execname(), filename) }’

先运行上面监测命令,当打开secrets文件时,终端上将显示对文件的操作!

使用systemtap调试linux内核

# 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不仅仅是一个简单的调试工具,强大的脚本语言能力让它同样能做一些有趣的事情,下面这个例子就可以对输出的字符进行美化:

使用systemtap调试linux内核

在进行性能分析的时候,我们常常需要知道那些函数调用次数最多,才能有的放矢地展开分析。下面这个简单的例子可以打印出在过去的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之所以受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:这个阶段,将编译好的内核模块插入内核,开始进行数据收集和传输。










上一篇:火车票订票系统的几点优化思考


下一篇:进程间通信(IPC)