type
status
date
slug
summary
tags
category
icon
password
🐝
从这篇开始会不定期写一些关于eBPF的内容,作为自己的备忘录。

eBPF基本概念

eBPF由BPF发展而来,其可以安全有效的观测并扩展内核的功能,并且无需修改内核源代码。
eBPF程序是事件驱动的,当内核或应用程序通过某个hook点时运行,预定义的hook包括系统调用、函数入口和退出、内核跟踪点、网络事件等。在预定义的hook点不能满足要求时,也可以创建kprobe和uprobe,以便在内核或用户程序的几乎任何位置附加eBPF程序。
notion image
下面贴出参考的一些资料,重复的内容就不复制粘贴了。

eBPF开发环境

对于ubuntu,可以使用以下指令快速安装需要的依赖和开发环境
但是对于多人协同开发环境,最好使用稳定的LLVM工具链,防止不同的LLVM版本带来的错误,对于固定版本的LLVM下载,使用以下指令(详细参考LLVM文档)。
完成基础环境的搭建之后,下面可以基于golang开发一个简单的eBPF程序,来串联开发流程。

CO-RE

首先先歪个楼,介绍一下CO-RE,这个部分重点关注的是eBPF程序的可移植性,eBPF程序由于会访问并处理大量的内核内部结构和内存数据,导致在运行时程序于所在内核具体实现耦合,为了达成CO-RE中Compile Once - Run Everywhere的目标,需要能够在内核数据结构和内存布局变化的情况下,通过一种“中间”描述来作为承接,对eBPF程序屏蔽内核结构的变化。
对于libbpf而言,其通过所在内核的BTF信息(在/sys/kernel/btf/vmlinux)来生成 vmlinux.h 文件,其包括了内核类型和数据结构布局相关的内容,可以通过如下方式来生成,通过这种方式消除了对内核头文件的依赖。

ebpf-go

回到正题,这里遵循了ebpf-c-program的教程,基于XDP开发了一个简单的统计网络收包数量的程序,相关的代码可以在ebpf-demo中找到,这里依赖的包比较少
相关的开发教程ebpf-c-program已经比较清晰,这里不再赘述,额外关注一下通过 go generate 生成的文件的区别,使用 bpf2go 会生成两组文件,分别如下:
  • *_bpfel.o 和 *_bpfel.go 用于 amd64、arm64、riscv64 和 loong64 等小端架构
  • *_bpfeb.o 和 *_bpfeb.go 用于 s390(x)、mips 和 sparc 等 big-endian 架构
两组文件都包含一个 go:embed 语句,该语句在编译时将相应 .o 文件的内容提取到一个字节切片中。结果是一个独立的 Go 应用程序二进制文件,可以部署到目标计算机,而不包含任何 .o 文件。为了进一步减少运行时依赖性,可以添加 CGO_ENABLED=0 进行构建,这样应用程序就不会依赖 libc,以下是一个示例。
 
strace&bpftraceeBPF map类型简介
Loading...
Patrickhao
Patrickhao
一个新手程序员
Announcement
🎉欢迎来到我的博客🎉
-- 这里会不定期更新 --
👏欢迎随时联系我👏