Home > Linux, 网络编程, 调优 > 用systemtap来修改下linux内核变量的值

用systemtap来修改下linux内核变量的值

October 29th, 2009

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

本文链接地址: 用systemtap来修改下linux内核变量的值

我们在探索linux内核的时候,经常需要调整下变量的值,看它对系统的影响。如果这个值没有透过/proc来修改的话,那只能编译内核。这个步骤是非常繁琐的。现在我们有systemtap这个利器来帮忙了。

演示如下:
我们通过修改过
extern int sysctl_tcp_fin_timeout;的值来达到目的。是因为这个值是proc导出的 我们好验证是否成功。

root@localhost ~]# cat /proc/sys/net/ipv4/tcp_fin_timeout
15000
[root@localhost ~]# cat test.stp
probe begin
{
        printf("ready go\n");
}

probe kernel.function("do_tcp_setsockopt")
{
        $sysctl_tcp_fin_timeout = $1
        printf("sysctl_tcp_fin_timeout = %d\n", $sysctl_tcp_fin_timeout);
        exit()
}

[root@localhost ~]# stap -g test.stp 18000
ready go

这个时候 stap在运行, 只是还没有触发do_tcp_setsockopt.
现在我们来触发

[root@localhost ~]# erl
Erlang R13B02 (erts-5.7.3) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.7.3  (abort with ^G)
1> {ok, LSock} = gen_tcp:listen(0, []).
{ok,#Port<0.437>}
2>
2> inet:setopts(LSock, [{nodelay,true}]).
ok
3>

Ok,这时候回头可以看到stap打出来以下:
sysctl_tcp_fin_timeout = 18000

我们来验证下:

root@localhost ~]# cat /proc/sys/net/ipv4/tcp_fin_timeout
18000

OK,成功。

Tips:
1. stap对全局变量的写需要-g guru模式。
2. 全局变量必须在一个单元内的函数里面才可以修改, 而且必须是在内核上下文。

PS. 这样写的话会更好,因为这个变量是单元可见的,这个模块里面的任何函数被触发都可以看到这个变量. 因为这是tcp的核心模块随时都会被出发的,免除了以上的麻烦!

$ cat test.stp
probe begin
{
        printf("ready go\n");
}
probe kernel.function("*@net/ipv4/tcp.c") 
//probe kernel.function("do_tcp_setsockopt")
{
        $sysctl_tcp_fin_timeout = $1
        printf("sysctl_tcp_fin_timeout = %d\n", $sysctl_tcp_fin_timeout);
        exit()
}

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

  1. September 24th, 2010 at 13:15 | #1
    [root@localhost ~]# cat test.stp
    global tmp=0
    probe kernel.function("do_tcp_setsockopt")
    {
            if(!tmp) next;
    
            $sysctl_tcp_fin_timeout=tmp;
            printf("done, sysctl_tcp_fin_timeout=%d\n", $sysctl_tcp_fin_timeout);
            exit();
    }
    
    
    probe procfs("sysctl_tcp_fin_timeout").write
    {
            tmp=strtol($value, 10);
            printf("sysctl_tcp_fin_timeout will be set to %d\n", tmp);
    }
    
    [root@localhost ~]# stap -m test -g test.stp
    
    #在另外的shell下运行
    [root@localhost ~]# echo 18000>/proc/systemtap/test/sysctl_tcp_fin_timeout 
    
    
  2. shiziwen
    October 11th, 2012 at 10:51 | #2

    您好,为什么按照上面的介绍修改变量之后,
    # cat /proc/sys/net/ipv4/tcp_fin_timeout
    0

    步骤如下:
    # stap -g kernel-variable.stp 15
    ready go
    sysctl_tcp_fin_timeout = 15

    # erl
    Erlang R15B02 (erts-5.9.2) [64-bit] [smp:12:12] [async-threads:0] [hipe] [kernel-poll:false]

    Eshell V5.9.2 (abort with ^G)
    1> {ok, LSock} = gen_tcp:listen(0, []).
    {ok,#Port}
    2> inet:setopts(LSock, [{nodelay,true}]).
    ok
    3> inet:setopts(LSock, [{nodelay,true}]).
    ok
    4>

    gaww Reply:

    stap -g kernel-variable.stp 5000
    # cat /proc/sys/net/ipv4/tcp_fin_timeout
    5

  3. shidao
    April 24th, 2014 at 15:19 | #3

    改全局变量的话,c语言写个ko,insmod更直接一些

    Yu Feng Reply:

    写KO不是每个人都会编译什么的,这个有门槛。

Comments are closed.