Systemtap examples, Network - 2 Tracing Functions Called in Network Socket Code

1 minute read

背景

这个例子来自socket-trace.stp 脚本, 跟踪内核中函数在net/socket.c代码中的调用和返回, 帮助用户从内核层面了解进程和网络的交互情况.  
脚本内容以及注解  
[root@db-172-16-3-150 network]# cd /usr/share/systemtap/testsuite/systemtap.examples/network  
[root@db-172-16-3-150 network]# cat socket-trace.stp   
#!/usr/bin/stap  
  
probe kernel.function("*@net/socket.c").call {  
  printf ("%s -> %s\n", thread_indent(1), probefunc())  
}  
// kernel.function("*@net/socket.c").call探针, 用了*通配符, net/socket.c所有函数的调用都会触发这个探针.  
// thread_indent(1), 同一个线程, 每次执行thread_indent时加1个空格.   
probe kernel.function("*@net/socket.c").return {  
  printf ("%s <- %s\n", thread_indent(-1), probefunc())  
}  
// thread_indent(-1), 与函数调用相反, 函数返回时, 这里同一个线程, 每次执行thread_indent时减1个空格.   
// 这样的话更容易看清除调用和返回的层次.  
// probefunc()函数用于输出当前地址对应的函数名. 从内核符号表中根据地址取出函数名.  

参考

http://blog.163.com/digoal@126/blog/static/1638770402013101381844107/

https://sourceware.org/systemtap/tapsets/API-probefunc.html

执行输出举例  
[root@db-172-16-3-150 network]# stap ./socket-trace.stp   
     0 init(1): -> sock_poll  
    15 init(1): <- do_select  
     0 init(1): -> sock_poll  
     4 init(1): <- do_select  
     0 portreserve(1545): -> sock_poll  
     9 portreserve(1545): <- do_select  
     0 udevd(1168): -> sock_poll  
     0 rpc.statd(1726): -> sock_poll  
     8 rpc.statd(1726): <- do_select  
     0 rpc.statd(1726): -> sock_poll  
     3 rpc.statd(1726): <- do_select  
     0 rpc.statd(1726): -> sock_poll  
     4 rpc.statd(1726): <- do_select  
     0 rpc.statd(1726): -> sock_poll  
     3 rpc.statd(1726): <- do_select  
     0 rpcbind(1595): -> sock_poll  
     9 rpcbind(1595): <- do_sys_poll  
     0 rpcbind(1595): -> sock_poll  
     4 rpcbind(1595): <- do_sys_poll  
     0 init(1): -> sock_poll  
     4 init(1): <- do_select  
     0 init(1): -> sock_poll  
     0 rpcbind(1595): -> sock_poll  
     4 rpcbind(1595): <- do_sys_poll  
     0 rpcbind(1595): -> sock_poll  
    14 init(1): <- do_select  
    95 udevd(1168): <- do_sys_poll  
     0 rpc.statd(1726): -> sock_poll  
    14 rpcbind(1595): <- do_sys_poll  
     0 rpcbind(1595): -> sock_poll  
     0 hald-addon-inpu(1874): -> sock_poll  
    14 rpcbind(1595): <- do_sys_poll  
    25 rpc.statd(1726): <- do_select  
  
probefunc()函数使用symname(addr) 或者 usymname(uaddr) 函数从内核表中取出对应的函数名:  
[root@db-172-16-3-150 network]# cat /boot/System.map-2.6.32-358.el6.x86_64 |grep sock_poll  
ffffffff81431450 t sock_poll  
例如把socket-trace.stp 改一下, 同时输出当前探针的地址信息, 则更可以看出probefunc()是通过符号表把地址转换成函数名的.  
如下 :   
[root@db-172-16-3-150 network]# vi socket-trace.stp   
#!/usr/bin/stap  
  
probe kernel.function("*@net/socket.c").call {  
  printf ("%s -> %p, %s\n", thread_indent(1), addr(), probefunc())  
}  
probe kernel.function("*@net/socket.c").return {  
  printf ("%s <- %p, %s\n", thread_indent(-1), addr(), probefunc())  
}  
  
[root@db-172-16-3-150 network]# stap ./socket-trace.stp   
     0 init(1): -> 0xffffffff81431450, sock_poll  
    17 init(1): <- 0xffffffff81197f42, do_select  
     0 init(1): -> 0xffffffff81431450, sock_poll  
     4 init(1): <- 0xffffffff81197f42, do_select  
     0 NetworkManager(1694): -> 0xffffffff81431450, sock_poll  
    15 NetworkManager(1694): <- 0xffffffff8119764b, do_sys_poll  
     0 NetworkManager(1694): -> 0xffffffff81431450, sock_poll  
     5 NetworkManager(1694): <- 0xffffffff8119764b, do_sys_poll  
     0 NetworkManager(1694): -> 0xffffffff81431450, sock_poll  
     5 NetworkManager(1694): <- 0xffffffff8119764b, do_sys_poll  
     0 NetworkManager(1694): -> 0xffffffff81431450, sock_poll  
     4 NetworkManager(1694): <- 0xffffffff8119764b, do_sys_poll  

参考

1. /usr/share/systemtap/testsuite/systemtap.examples

2. https://sourceware.org/systemtap/SystemTap_Beginners_Guide/useful-systemtap-scripts.html

3. systemtap-testsuite

4. https://sourceware.org/systemtap/examples/

5. /usr/share/systemtap/testsuite/systemtap.examples/index.txt

6. /usr/share/systemtap/testsuite/systemtap.examples/keyword-index.txt

7. /usr/share/systemtap/tapset

8. /usr/src/debug/kernel-2.6.32-358.el6/linux-2.6.32-358.el6.x86_64/net/socket.c

9. http://blog.163.com/digoal@126/blog/static/16387704020131071118496/

10. https://sourceware.org/systemtap/tapsets/API-probefunc.html

11. http://blog.163.com/digoal@126/blog/static/1638770402013101381844107/

Flag Counter

digoal’s 大量PostgreSQL文章入口