前面都是通过BPF来load 一个函数到kernel space,其实还可以通过BPF load 一个c的源码包到kernel space,并且可以在
要监控的函数进入和推出是分别调用回调函数
#!/usr/bin/python
#
from bcc import BPF
#导入第三方库,这样python中就可以用c中定义的变量
from ctypes import c_ushort, c_int, c_ulonglong
from time import sleep
from sys import argv
def usage():
print("USAGE: %s [interval [count]]" % argv[0])
exit()
# arguments
interval = 5
count = -1
if len(argv) > 1:
try:
interval = int(argv[1])
if interval == 0:
raise
if len(argv) > 2:
count = int(argv[2])
except: # also catches -h, --help
usage()
# load BPF program
#将vfsreadlat.c 这个.c load到kernel space
b = BPF(src_file = "vfsreadlat.c")
#设定vfs_read进入的时候调用do_entry,这个函数定义在vfsreadlat.c 中
b.attach_kprobe(event="vfs_read", fn_name="do_entry")
#设定vfs_read离开的时候调用do_entry,这个函数定义在vfsreadlat.c 中
b.attach_kretprobe(event="vfs_read", fn_name="do_return")
# header
#python中打印log
print("Tracing... Hit Ctrl-C to end.")
# output
loop = 0
do_exit = 0
#简单的while死循环
while (1):
if count > 0:
loop += 1
if loop > count:
exit()
try:
sleep(interval)
except KeyboardInterrupt:
pass; do_exit = 1
print
#以2的次方打印count,以usecs为head
b["dist"].print_log2_hist("usecs")
#清空这个变量
b["dist"].clear()
#变量do_exit 在用户按住CTRL+C 的时候会为1,因此这里就退出while这个死循环了
if do_exit:
exit()
vfsreadlat.c的源码如下:
#include <uapi/linux/ptrace.h>
BPF_HASH(start, u32);
BPF_HISTOGRAM(dist);
int do_entry(struct pt_regs *ctx)
{
u32 pid;
u64 ts, *val;
pid = bpf_get_current_pid_tgid();
ts = bpf_ktime_get_ns();
start.update(&pid, &ts);
return 0;
}
int do_return(struct pt_regs *ctx)
{
u32 pid;
u64 *tsp, delta;
pid = bpf_get_current_pid_tgid();
tsp = start.lookup(&pid);
if (tsp != 0) {
delta = bpf_ktime_get_ns() - *tsp;
dist.increment(bpf_log2l(delta / 1000));
start.delete(&pid);
}
return 0;
}
最终打印的结果为
Tracing... Hit Ctrl-C to end.
usecs : count distribution
0 -> 1 : 0 | |
2 -> 3 : 2 |*********** |
4 -> 7 : 7 |****************************************|
8 -> 15 : 4 |********************** |
usecs : count distribution
0 -> 1 : 29 |****************************************|
2 -> 3 : 28 |************************************** |
4 -> 7 : 4 |***** |
8 -> 15 : 8 |*********** |
16 -> 31 : 0 | |
32 -> 63 : 0 | |
64 -> 127 : 0 | |
128 -> 255 : 0 | |
256 -> 511 : 2 |** |
512 -> 1023 : 0 | |
1024 -> 2047 : 0 | |
2048 -> 4095 : 0 | |
4096 -> 8191 : 4 |***** |
8192 -> 16383 : 6 |******** |
16384 -> 32767 : 9 |************ |
32768 -> 65535 : 6 |******** |
65536 -> 131071 : 2 |** |
usecs : count distribution
0 -> 1 : 11 |****************************************|
2 -> 3 : 2 |******* |
4 -> 7 : 10 |************************************ |
8 -> 15 : 8 |***************************** |
16 -> 31 : 1 |*** |
32 -> 63 : 2 |******* |
Lesson 11. vfsreadlat.py
最新推荐文章于 2024-03-29 00:37:01 发布