记得 5 年前刚接触 perf 的时候,还特意调研了一下不同系统上的动态和静态追踪工具,知道了 Linux 上的 SystemTap,perf。Solaris 上的 DTrace。看到绝大多数资料都说 DTrace 多么的强大好用,但是 Linux 却没有与之相提并论的工具。
最近看到 BPF 这三个字被提及的很频繁,搜索了一下发现它号称 “Linux 中的 DTrace”, 于是试着玩了一下。
BPF 全称是 “Berkeley Packet Filter”,字面意思是包过滤器,那么问题来了:我一个包过滤器,怎么就成了追踪调试工具呢? 这主要是因为一些历史的进程:原先开发 BPF 的目的是在内核重定向数据包,接着增加了对事件的追踪功能,然后又增加了基于时间的采样,于是久而久之 BPF 就成了一个功能强大的调试工具。
安装
首先,内核版本最好大于 4.9 , 可以用 uname -a
命令查看。
其次,查看一下内核在编译的时候是否开启了 BPF 选项,一般在 /boot/ 目录下有对应内核版本的 config 文件,比如在我的机器上是 /boot/config-4.15.0-30-generic
。 如果看到 CONFIG_BPF_SYSCALL=y
说明可以用 BPF 的基本功能。
前面提到 BPF 号称 Linux 中的 DTrace,为什么呢? 因为 DTrace 包含了一个类似脚本语言的 D 语言,用户可以用简单的几句 D 语言完成复杂的调试追踪任务,这一点是 perf 做不到,而 BPF 做到了。
确认了内核支持 BPF 之后,我们可以安装一个叫做 bcc 的工具,通过它可以方便的使用 BPF。
BCC - Tools for BPF-based Linux IO analysis, networking, monitoring
如果是 Ubuntu 系统,可以添加源
1. sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys D4284CDD
2. echo "deb https://repo.iovisor.org/apt/bionic bionic main" |\
sudo tee /etc/apt/sources.list.d/iovisor.list
3. sudo apt-get install bcc-tools
然后就能用 apt 命令 install bcc 了。
使用
在系统中安装好 bcc 之后,再下载一份源码,因为想试玩 tools 目录下的几十个工具。
tcpconnect.py 跟踪系统中所有的 tcp connect() 调用。
> openssl s_client -connect google.com:443
root@ubuntu:~/bcc/tools# ./tcpconnect.py
PID COMM IP SADDR DADDR DPORT
11493 openssl 4 192.168.122.167 216.58.195.78 443
开发
随便打开一个 py 文件,都能看到像下面这样的一段代码,这就是类似 DTrace 的 D 语言那样,用较高级的语言,通过即时编译,完成复杂的追踪调试任务。BPF 最核心的优势也在于此。
bpf_text =
#include <uapi/linux/ptrace.h>
#define KBUILD_MODNAME "foo"
#include <linux/tcp.h>
#include <net/sock.h>
#include <bcc/proto.h>
BPF_HASH(last, struct sock *, u64);
// separate data structs for ipv4 and ipv6
struct ipv4_data_t {
u64 ts_us;
u64 skaddr;
u64 saddr;
u64 daddr;
u64 span_us;
u32 pid;
u32 ports;
u32 oldstate;
u32 newstate;
char task[TASK_COMM_LEN];
};
争取下次可以自己开发一个小工具。happy hacking