Systemtap PROCFS probes
背景
systemtap 虚拟文件交互探针, 在/proc/systemtap/MODNAME目录下对指定文件读写时触发.
These probe points allow procfs pseudo-files in /proc/systemtap/MODNAME to be created, read and written. Specify the name of the systemtap module as MODNAME. There are four probe point variants supported by the translator:
procfs("PATH").read
procfs("PATH").write
procfs.read
procfs.write
PATH is the file name to be created, relative to /proc/systemtap/MODNAME. If no PATH is specified (as in the last two variants in the previous list), PATH defaults to "command".
When a user reads /proc/systemtap/MODNAME/PATH, the corresponding procfs read probe is triggered. Assign the string data to be read to a variable named $value, as follows:
procfs("PATH").read { $value = "100\n" }
When a user writes into /proc/systemtap/MODNAME/PATH, the corresponding procfs write probe is triggered. The data the user wrote is available in the string variable named $value, as follows:
procfs("PATH").write { printf("User wrote: %s", $value) }
MODNAME不固定, 随机生成, PATH指文件名, PATH不指定的话默认名为command.
例如 :
以下探针在用户读取command时, 内容为$value指定的”abc\n”
[root@db-172-16-3-39 ~]# stap --vp 05 -e 'probe procfs.read { $value = "abc\n"; }'
Eliding side-effect-free singleton block operator '{' at <input>:1:19
Pass 2: analyzed script: 1 probe(s), 1 function(s), 1 embed(s), 0 global(s) using 147764virt/24452res/3256shr/22360data kb, in 10usr/0sys/6real ms.
stap执行后, 自动创建MODNAME, 如下 :
[root@db-172-16-3-39 ~]# lsmod|grep stap
stap_c8e98652dbf72a846df6f69d72aa98de_1058 74144 2
进入/proc/systemtap/stap_c8e98652dbf72a846df6f69d72aa98de_1058/目录, 可以看到名为command的文件.
[root@db-172-16-3-39 ~]# cd /proc/systemtap/stap_c8e98652dbf72a846df6f69d72aa98de_1058/
[root@db-172-16-3-39 stap_c8e98652dbf72a846df6f69d72aa98de_1058]# ll
total 0
-r-------- 1 root root 0 Oct 6 08:06 command
用户读取这个文件时, 探针触发, 并输出给用户$value值abc\n.
[root@db-172-16-3-39 stap_c8e98652dbf72a846df6f69d72aa98de_1058]# cat command
abc
PATH命名探针举例 :
[root@db-172-16-3-39 ~]# stap --vp 05 -e 'probe procfs("digoal").read { $value = "abc\n"; }'
Eliding side-effect-free singleton block operator '{' at <input>:1:29
Pass 2: analyzed script: 1 probe(s), 1 function(s), 1 embed(s), 0 global(s) using 148284virt/24444res/3256shr/22880data kb, in 10usr/0sys/6real ms.
[root@db-172-16-3-39 ~]# cd /proc/systemtap/stap_c6373a2dc49ccd7f60f51cb02d421026_1078/
[root@db-172-16-3-39 stap_c6373a2dc49ccd7f60f51cb02d421026_1078]# ll
total 0
-r-------- 1 root root 0 Oct 6 08:06 digoal
[root@db-172-16-3-39 stap_c6373a2dc49ccd7f60f51cb02d421026_1078]# cat digoal
abc
写探针举例, 当用户写文件时, 在探针的handler中可以通过$value读取到用户往文件写入的值.
[root@db-172-16-3-39 ~]# stap --vp 05 -e 'probe procfs("digoal").write { printf("%s", $value) }'
Eliding side-effect-free singleton block operator '{' at <input>:1:30
Pass 2: analyzed script: 1 probe(s), 1 function(s), 1 embed(s), 0 global(s) using 147320virt/24428res/3248shr/21916data kb, in 10usr/0sys/6real ms.
往虚拟文件中写入两行 :
[root@db-172-16-3-39 ~]# cd /proc/systemtap/stap_96658768b416c658023814c8d71d4eb9_1098/
[root@db-172-16-3-39 stap_96658768b416c658023814c8d71d4eb9_1098]# echo -e "Hello, I'm digoal\nWho are you?\n" > ./digoal
执行完以上写入后, 探针的handler, printf(“%s”, $value)输出了用户使用echo -e “Hello, I’m digoal\nWho are you?\n” > ./digoal写入的值.
Pass 2: analyzed script: 1 probe(s), 1 function(s), 1 embed(s), 0 global(s) using 147320virt/24428res/3248shr/21916data kb, in 10usr/0sys/6real ms.
Hello, I'm digoal
Who are you?
读写探针举例 :
[root@db-172-16-3-39 ~]# stap --vp 05 -e 'probe procfs("digoal").read { $value = "abc\n"; } probe procfs("digoal").write { printf("%s", $value) }'
Eliding side-effect-free singleton block operator '{' at <input>:1:29
Eliding side-effect-free singleton block operator '{' at <input>:1:80
Pass 2: analyzed script: 2 probe(s), 2 function(s), 1 embed(s), 0 global(s) using 147328virt/24460res/3264shr/21924data kb, in 0usr/0sys/6real ms.
[root@db-172-16-3-39 systemtap]# lsmod|grep stap
stap_b8c49f4eed3186e72a6dc47a0ffe4c8b_1410 76320 2
[root@db-172-16-3-39 systemtap]# cd /proc/systemtap/stap_b8c49f4eed3186e72a6dc47a0ffe4c8b_1410/
[root@db-172-16-3-39 stap_b8c49f4eed3186e72a6dc47a0ffe4c8b_1410]# ll
total 0
-rw------- 1 root root 0 Oct 6 08:12 digoal
[root@db-172-16-3-39 stap_b8c49f4eed3186e72a6dc47a0ffe4c8b_1410]# cat digoal
abc
[root@db-172-16-3-39 stap_b8c49f4eed3186e72a6dc47a0ffe4c8b_1410]# echo -e "Hello, I'm digoal\nWho are you?\n" > ./digoal
Pass 2: analyzed script: 2 probe(s), 2 function(s), 1 embed(s), 0 global(s) using 147324virt/24456res/3264shr/21920data kb, in 0usr/0sys/6real ms.
Hello, I'm digoal
Who are you?
最后, 使用procfs探针注意, 如果用户未退出虚拟文件系统目录, 例如/proc/systemtap/stap_96658768b416c658023814c8d71d4eb9_1098/, 那么在探针结束时,如 Ctrl+C, 不能及时收回mod. 对于这种情况可以退出改目录, 使用rmmod删除对应的mod.
[root@db-172-16-3-39 ~]# stap --vp 05 -e 'probe procfs.read { $value = "abc\n"; }'
Eliding side-effect-free singleton block operator '{' at <input>:1:19
Pass 2: analyzed script: 1 probe(s), 1 function(s), 1 embed(s), 0 global(s) using 148280virt/24432res/3256shr/22876data kb, in 10usr/0sys/6real ms.
Error inserting module '/tmp/stapLYrleG/stap_c8e98652dbf72a846df6f69d72aa98de_1058.ko': File exists
WARNING: /usr/bin/staprun exited with status: 1
Pass 5: run failed. Try again with another '--vp 00001' option.
[root@db-172-16-3-39 ~]# lsmod|grep stap
Module Size Used by
stap_a8bfea9ea582644b887b62bb4323e296_1370 76192 1
stap_c8e98652dbf72a846df6f69d72aa98de_1058 74144 0
[root@db-172-16-3-39 ~]# rmmod stap_c8e98652dbf72a846df6f69d72aa98de_1058
[root@db-172-16-3-39 ~]# rmmod stap_a8bfea9ea582644b887b62bb4323e296_1370
ERROR: Module stap_a8bfea9ea582644b887b62bb4323e296_1370 is in use
[root@db-172-16-3-39 ~]# lsmod|grep stap
stap_a8bfea9ea582644b887b62bb4323e296_1370 76192 0
[root@db-172-16-3-39 stap_a8bfea9ea582644b887b62bb4323e296_1370]# cd
[root@db-172-16-3-39 ~]# rmmod stap_a8bfea9ea582644b887b62bb4323e296_1370
参考
1. https://sourceware.org/systemtap/langref/Probe_points.html#SECTION00056000000000000000
2. man lsmod, rmmod, modinfo