在 WSL 上使用 eBPF
1. 什么是 WSL
WSL
(Windows Subsystem for Linux) 可以理解为 Windows 为 Linux 提供的一个子系统。在Win
系统上,对于基本的业务开发,WSL
可以满足我们对 Linux 操作系统的基本需求,而不是重新装双系统。一些开发诉求:
- 特定的 Linux 发行版(Ubuntu or Debian)
- 更友好的命令行界面及工具(cat, ls)
- 运行在 Linux 环境中的各种软件(GCC, vim, ssh)
WSL 已经发展到第二代了(官方称 WSL2,本文也使用的是 WSL2,但为了表述方便,后文都简称为 WSL)。它拥有完整的 Linux 内核,几乎就是一个独立的虚拟机了。
但是 WSL 也没有完全基于社区版的 Linux 内核,也是进行了一些定制化魔改,所以在一些功能上还是有些区别。例如,在构建 eBPF 程序时,就会遇到这个错误:
modprobe: FATAL: Module kheaders not found in directory /lib/modules/xxx
另外, WSL 默认也没有开启 BTF 这个内核选项,在使用CO,RE
的特性时也会有一点问题。
写文章时,内核版本为 5.10.6 的 WSL 还没有开启
BTF
选项,后面对 WSL 整体升级后(5.10.102),BTF
选项自动开启了。
要解决上面的问题,就需要重新编译内核了。
2. 编译内核
2.1 获取源码
首先查看自己机器的内核版本,本人的 WSL 基于 Ubuntu。
然后去官方仓库(https://github.com/microsoft/WSL2-Linux-Kernel/releases)的 release 页面下载和自己内核版本对应的源代码。
解压,进入该目录,得到如下内容(目录名太长了,我改了名)。
|
|
2.2 更改编译选项
如果是高版本内核,一些最基础的eBPF
功能默认都是开启的(Kprobe 和 Tracepoint 这类),这里不全部列出了,只列出WSL
内核未开启的,以及一些可选高级功能。
|
|
修改完后,保存退出,下面开始编译内核。
2.3 编译及模块安装
|
|
第一步 make 时间比较久,如果看到下面的结果,就说明编译成功了。若 echo 的结果不为 0,就说明上一条指令异常退出,需要解决错误后重新编译。
可以在/lib/modules/$(uname -r)
下看到安装的一些模块。
刚生成的 BTF 信息:
/sys/kernel/debug/
路径下也有比较重要的信息:trace_pipe,tracepoint 的各种定义等。这个目录默认是空的,我们需要手动挂载一下。
|
|
3. 其它工具的安装
bpftool
是比较常用的一个工具,可用来基于 libbpf 开发生成 skeleton,查看系统上已加载的 eBPF 程序等。详细的使用技巧可以参考:bpftool-features-thread。
内核源码中也有bpftool
的源代码,因此直接编译安装是最推荐的做法。
|
|
4. bpftrace 测试
统计一段时间内,各应用执行系统调用的次数。
|
|
使用 bpftool 来查看刚才加载到内核的 eBPF 程序。
这说明WSL
下的 eBPF 环境应该是搭建好了,后面就可以在该环境下开发和运行 eBPF 程序了。