Home > Erlang探索, Linux, 工具介绍 > Systemtap的另类用法

Systemtap的另类用法

November 10th, 2010 Leave a comment Go to comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: Systemtap的另类用法

通常我们在做内核编程的时候,会用到内核的数据结构,比如说textsearch提供了几种算法用于支付串查找。在用于正式的项目前,我们会希望考察下他的用法以及想体验下。最通常的做法是自己写个module,写个makefile,编译,运行,然后去dmesg里面看printk的结果。这个过程没啥问题,就是太罗嗦。好了,现在我们有更方便的方法了:systemtap.

Systemtap是个脚本,先翻译成c kernel模块代码,然后编译,插入到内核运行,同时提供最基本的内核和应用模块的通讯管道,在应用模块这里收集信息。 它还支持guru模式,让用户直接插入c代码。 这样我们就可以利用stap的这一特性来做我们的实验。

底下我们来演示下:

# cat ts.stp
%{
#include <linux/textsearch.h>
%}
function test_textsearch:long (algo:string) %{ /* pure */ /* unprivileged */
struct ts_config* ts;
struct ts_state state;

ts = textsearch_prepare(THIS->algo, "world", 5, GFP_KERNEL, TS_AUTOLOAD);
if(IS_ERR(ts)) goto err;
_stp_printf("%s\n", "prepare ok!");
if(UINT_MAX==textsearch_find_continuous(ts, &state, "hello world", 11)) goto err;
_stp_printf("%s\n", "find ok!");
textsearch_destroy(ts);
THIS->__retvalue = 0;
return;
err:
_stp_printf("%s\n", "init error!");
THIS->__retvalue = -1;
return;
%}

probe begin
{
printf("result:%d\n", test_textsearch(@1));
exit();
}

%%请注意我们上面用到了 _stp_printf,代替printk, 这个是stap的runtime的基础服务。

# stap -gu ts.stp bm %%我们用的是BM算法
prepare ok!
find ok!
result:0

cool吧! 把c语言当脚本编写啦。

但是这个stap有个缺点,就是头文件必须是内核include路径里面的,如果我们用到了其他头文件,编译的时候就出错。

# touch xyz.h #建个空的头文件
# diff -u ts.stp ts1.stp
--- ts.stp      2010-11-08 12:04:54.000000000 +0800
+++ ts1.stp     2010-11-10 14:19:47.000000000 +0800
@@ -1,5 +1,6 @@
 %{
 #include <linux/textsearch.h>
+#include "xyz.h"
 %}
 
# stap -gu ts1.stp bm
/tmp/stapKuLo9R/stap_90d03f83d4d4a8efa7b721a6ff0093fe_2503.c:169:17: error: xyz.h: No such file or directory
make[1]: *** [/tmp/stapKuLo9R/stap_90d03f83d4d4a8efa7b721a6ff0093fe_2503.o] Error 1
make: *** [_module_/tmp/stapKuLo9R] Error 2
Pass 4: compilation failed.  Try again with another '--vp 0001' option.

这个问题挺烦人的,但是我们有探索精神,不怕的,我们来crack下吧

# diff systemtap-1.3/buildrun.cxx systemtap-1.3.patched/buildrun.cxx 
235a236,238
> 
>   o << "EXTRA_CFLAGS += $(STAP_CFLAGS)" << endl;
> 
237a241
>
# ./configure --prefix=/usr && make && make install

到现在为止 stap是crack过的. 我们再来实验下吧!首先把我们的头文件所在的路径通知到systemtap,它会在让编译模块的时候加上我们的头文件路径。

# export STAP_CFLAGS="-I`pwd`"
# printenv STAP_CFLAGS
-I/home/wentong

# stap -gu ts1.stp bm
prepare ok!
find ok!
result:0

哈哈,成功了。

大家可以这样的方式用stap写很多好玩的东西,祝玩的开心。

Post Footer automatically generated by wp-posturl plugin for wordpress.

  1. 文通
    November 10th, 2010 at 14:30 | #1

    顶沙发

    [Reply]

    Yu Feng Reply:

    谢谢文通支持哦!!!

    [Reply]

  2. wuyun.xl
    November 10th, 2010 at 14:31 | #2

    果然需要一定的底层基础。。。

    [Reply]

  3. November 10th, 2010 at 14:34 | #3

    好东西要顶

    [Reply]

  4. 丁奇
    November 10th, 2010 at 14:35 | #4

    还游离在printf pid()的路过

    我果然还要再看三百年才能搞到这层次么

    直接拷贝走源码了

    [Reply]

    Yu Feng Reply:

    工具嘛!熟练了了能提高生产力!

    [Reply]

  5. zituan
    November 10th, 2010 at 14:51 | #5

    褚霸兄非常了不起,把我们从麻烦的module_init()/module_exit()中解救出来了,
    不仅方便,还大大降低了一些需要硬编码指针地址的风险

    [Reply]

    Yu Feng Reply:

    子团兄过奖了,你才是真正的牛人哦!!!

    [Reply]

  6. 范慎
    November 10th, 2010 at 17:04 | #6

    真羡慕啊~~做底层一直是我的梦想

    [Reply]

    Yu Feng Reply:

    底层开发貌似会感觉有成就感些!

    [Reply]

  7. November 15th, 2010 at 11:35 | #7

    确实好用,不过对底层知识的要求貌似较高啊..

    [Reply]

    Yu Feng Reply:

    探测用户空间的程序就无需懂太多内核知识。

    [Reply]

  8. fengmao
    April 10th, 2013 at 10:41 | #8

    hi, 你分享的方法,确实是很有用。
    我想通过systemtap插入c++代码。
    我发现一个问题,如果自定义的文件里面有c++的头文件的话,就会提示找不到头文件。 分析原因发现,systemtap将脚本翻译成c语言,然后用gcc来编译。这样的话,找不到头文件。

    那我有什么办法可以通过systemtap插入c++代码呢?感谢

    [Reply]

    Yu Feng Reply:

    kernel是c实现的,用c++很不安全。

    [Reply]

  9. jmchen
    May 15th, 2013 at 12:26 | #9

    翻到您的这篇古文:)将俺从手写include文件路径中解脱出来了。谢谢谢谢

    [Reply]

    Yu Feng Reply:

    呵呵,方便你就好~

    [Reply]

  1. November 14th, 2010 at 19:23 | #1
  2. February 26th, 2013 at 14:00 | #2