1. 参考资料
在eBPF的学习过程中,主要是跟着Linux内核之旅开源社区进行学习,在此非常感谢Linux内核之旅开源社区让我少走了很多的弯路,这种乐于分享的精神值得敬佩与学习。
2. eBPF编程方法分类
eBPF编程方法主要有如下几种,本文主要记录eBPF C编程的环境搭建与程序编写。bcc安装和简单示例在后面会介绍。
3. 安装ubuntu20.04
相关资料很多,就不重复造轮子了,贴一下资源路径:
4. 安装ubuntu20.04后可能会出现的问题与解决方法
4.1 ubuntu20.04和windows共享文件夹设置
VMware:Ubuntu虚拟机/mnt/hgfs 下没有共享文件夹,解决办法
4.2 更新源sourcelist:
idle@linux:/$ sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
//使用aliyun上的源进行替换:
idle@linux:/$ sudo vi /etc/apt/sources.list
sudo apt-get update
sudo apt-get upgrade
4.3 ubuntu和windows之间复制与粘贴
sudo apt-get autoremove open-vm-tools
sudo apt-get install open-vm-tools
sudo apt-get install open-vm-tools-desktop
然后执行 reboot 命令重启ubuntu
4.4 VMware中Ubuntu虚拟机链接wifi
解决VMware中Ubuntu虚拟机无法连接本机wifi的问题
5. 搭建eBPF C程序运行环境
5.1 下载linux源码
下载与所安装的ubuntu内核版本相同的linux源码:
1、查看ubuntu内核版本
2、apt下载,git clone 或者windows上下载好复制过来都可,将源码解压在/usr/src/目录下。我采用的是windows上下载,然后通过共享文件夹发送给ubuntu。linux源码下载地址
3、在ubuntu的共享文件夹中可看到对应文件
4、将linux-5.13.tar.gz拷贝到其他文件夹
5、将linux-5.13.tar.gz解压到/usr/src下
5.2 安装依赖文件
sudo apt install libncurses5-dev flex bison libelf-dev binutils-dev libssl-dev
使用以下两条命令分别安装 clang 和 llvm
sudo apt install clang
sudo apt install llvm
安装成功的标志如下:
5.3 配置内核
//安装make
sudo apt install make
在源码根目录/usr/src/linux-5.13下使用make defconfig生成.config文件。可以执行make menuconfig来可视化的查看内核配置选项,目前可不进行内核配置。
//生成.config文件
make defconfig
//关联内核头文件
make headers_install
//编译内核
make -j8
6. 编译内核eBPF样例
Linux内核源码里包含了大量的eBPF示例代码,非常适合学习者阅读和测试。示例代码里基本是kern和user成对出现,也就是对于一个示例来说,分别提供了在内核空间运行的和用户空间运行的程序。
如果对eBPF纯C程序的组成不太了解的话,可参考
在源代码根目录下执行make M=samples/bpf,可以在samples/bpf/文件夹中看到已经生成了eBPF的可执行文件。
7. 编写自己的eBPF程序
编写自己的eBPF程序,只需要在samples/bpf/文件夹中编写hello_kern.c,hello_user.c以及修改Makefile即可,最后在源代码根目录下执行make M=samples/bpf,就可以在samples/bpf/文件夹中看到自己的bpf程序生成了可执行文件。
7.1 第一步,编写hello_kern.c文件
#include <linux/ptrace.h>
#include <linux/version.h>
#include <uapi/linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include "trace_common.h"
SEC("kprobe/" SYSCALL(sys_write))
int bpf_prog(struct pt_regs *ctx) {
char msg[] = "hello world!\n";
bpf_trace_printk(msg, sizeof(msg));
return 0;
}
char _license[] SEC("license") = "GPL";
7.2 第二步,编写hello_user.c文件
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include <linux/bpf.h>
#include <fcntl.h>
#define DEBUGFS "/sys/kernel/debug/tracing/"
void read_trace_pipe(void)
{
int trace_fd;
trace_fd = open(DEBUGFS "trace_pipe", O_RDONLY, 0);
if (trace_fd < 0)
return;
while (1) {
static char buf[4096];
ssize_t sz;
sz = read(trace_fd, buf, sizeof(buf) - 1);
if (sz > 0) {
buf[sz] = 0;
puts(buf);
}
}
}
int load_bpf_file(const char* object_name) {
struct bpf_object *objs;
struct bpf_program *prog;
struct bpf_link *link = NULL;
printf("%s\n", object_name);
objs = bpf_object__open_file(object_name, NULL);
if (libbpf_get_error(objs)) {
fprintf(stderr, "open object file error!\n");
goto cleanup;
return -1;
}
prog = bpf_object__find_program_by_name(objs, "bpf_prog");
if (!prog) {
fprintf(stderr, "ERROR: finding a prog in obj file failed\n");
goto cleanup;
return -1;
}
if (bpf_object__load(objs)) {
fprintf(stderr, "load object file error!\n");
goto cleanup;
return -1;
}
link = bpf_program__attach(prog);
if (libbpf_get_error(link)) {
fprintf(stderr, "ERROR: bpf_program__attach failed\n");
goto cleanup;
return -1;
}
return 0;
cleanup:
bpf_link__destroy(link);
bpf_object__close(objs);
return -1;
}
int main() {
if (load_bpf_file("/usr/src/linux-5.13/samples/bpf/hello_kern.o")) {
return -1;
}
read_trace_pipe();
return 0;
}
7.3 第三步,修改Makefile文件
我们修改Makefile时只需要修改三处,分别在对应的位置添加tprogs-y += hello、hello-objs := hello_user.o、always-y += hello_kern.o,修改后的完整的Makefile文件如下:
tprogs-y += xdp_sample_pkts
tprogs-y += ibumad
tprogs-y += hbm
tprogs-y += hello
xdp_sample_pkts-objs := xdp_sample_pkts_user.o
ibumad-objs := ibumad_user.o
hbm-objs := hbm.o $(CGROUP_HELPERS)
hello-objs := hello_user.o
always-y += hbm_out_kern.o
always-y += hbm_edt_kern.o
always-y += xdpsock_kern.o
always-y += hello_kern.o
7.4 运行eBPF程序并查看结果
在源代码根目录下执行make M=samples/bpf,在samples/bpf/文件夹中查看自己的bpf程序生成的可执行文件。
执行此eBPF程序
idle@linux:/usr/src/linux-5.13/samples/bpf$ sudo ./hello
至此ubuntu20.04 eBPF纯C程序的环境搭建与示例操作完毕,后续可以开始深入理解eBPF的原理与应用了。