使用systemtap获得内核局部变量
这两天在看内核的cgroup源码,就想着通过某个工具来获得一些调试信息如bt,参数返回值等,像在调试应用程序一样使用gdb来获得这些信息。所以就有了对systemtap的真正实践。注:我测试的机器使用的内核是:2.6.32-220.23.1.tb704.el6.x86_64(这是我们公司的内核),我看的源码是http://www.kernel.org/下载的2.6.32-60。
这里我们不再介绍systemtap的安装,只是需要知道要使用systemtap必须安装相应内核的符号信息debuginfo。
Systemtap支持嵌入C代码,这是获得函数内局部变量的关键。注:运行脚本时使用加-g参数,所有嵌入的C代码必须用%{ … %}包括起来(不是%{…}%),另外头文件也需要使用这对符号包括起来(《hack debug》里面就没把头文件包含在%{%}里);嵌入的C代码不能调用阻塞式函数。
首先我想获得一个参数其中的一个字段(该参数是一个结构体,并且传递的是指针),使用$variable可以获得参数的值,那么怎么来获得它的某一字段的值:function root_name:long(arg:long) %{
struct cgroup_sb_opts *opts = (struct cgroup_sb_opts *)(THIS->arg);
THIS->__retvalue = opts->subsys_bits;
%}
在systemtap内指针值是long类型,我们的指针指向的是struct cgroup_sb_opts,所以我们先进行一次类型转换,然后就可以用C语言的方式来获得它的字段值。注:如果该类型(struct cgroup_sb_opts)不在内核的头文件里,那么还必须手动定义该类型(可能需要递归定义所有的不在头文件里的类型)。如果返回的是string类型,则使用strlcpy (THIS->__retvalue, opts->name, MAXSTRINGLEN)来返回。提示:如果嵌入的C语言有错误或者警告,stap输出的信息的位置是它生成的临时C文件的位置,而不是我们的脚本位置,这样调试起来就很不方便,所以我们要保留这些临时文件(加-k选项),然后再去找它报的错误位置,这样就可以很容易定位到我们脚本的错误位置。 上面是一个简单的运用,因为我们直接获得的是参数的值,那么如果想获得运行中的内部局部变量的值?