bpftrace是在eBPF和BCC上构建的一个简化的跟踪工具,可以通过几行简单的脚本实现复杂的跟踪功能,在编写简单的eBPF程序就可以实现功能的情况下,可以使用bpftrace。在高版本内核(4.x)中能够直接使用bpftrace。下述环境是在CentOS 8-Stream,4.18.0的内核中进行的实验。bpftrace需要提前安装:
yum install -y bpftrace
查看bpftrac能够跟踪的所有内核跟踪点:
bpftrace -l
跟踪点一般可以分为tracepoint(内核静态探针)、kprobe(内核动态函数指针)和kfunc(基于bpf的内核动态函数指针),kprobe和kfunc是不稳定接口,tracepoint是稳定接口,有限选择使用tracepoint接口,能够保证在不同版本的内核中的可移植性。
在BTF可用的前提下,能够使用bpftrace来打印内核中的结构体定义,例如
bpftrace -vl "kvmppc_xive"
查询一个函数的入参:
bpftrace -lv tracepoint:syscalls:sys_enter_execve
跟踪系统调用的入参值:
bpftrace -e 'tracepoint:syscalls:sys_enter_execve {join(args->argv);}'
bpftrace -e 'tracepoint:syscalls:sys_exit_execve { printf("%-6d %-8s ret=%d \n",pid,comm,args->ret); }'
查看内核函数调用栈
bpftrace -e 'kprobe:vfs_open { @[kstack(perf)] = count(); }'
除了可以使用bpftrace来跟踪内核态,还可以使用bpftrace来跟踪用户态程序,例如下面的test.c文件
#include <stdio.h>
int main(int argc, char **argv) {
printf("hello world!\n"); return 0;
}
编译
gcc -g -o test test.c
使用bpftrace获取返回值:
bpftrace -e 'uretprobe:/home/gjw/test:main {printf("%d\n", retval);}'
查看所有的可跟踪点uprobe和uretprobe
bpftrace -vl 'uprobe:/home/test:*' bpftrace -vl 'uretprobe:/home/test:*'
除了上述tracepoint、kprobe、kfunc、uprobe、uretprobe探针外,bpftrace还有针对hardware和software的探针
bpftrace -l | grep software bpftrace -l | grep hardware