淘宝美工网站怎么做,企鹅自媒体平台注册,wordpress怎么改密码忘记,wordpress superchangerGo 语言  libbpfgo 实战 eBPF 开发 
1. 引言 
这是专栏的第一篇文章#xff0c;我们将从环境准备、示例代码运行和详解三个方面#xff0c;带你快速入门 eBPF 开发。 
#x1f4cc; 读完这篇文章#xff0c;你将学会#xff1a; ✔️ 如何用 Go  libbpfgo 开发 eBPF 程序。…Go 语言  libbpfgo 实战 eBPF 开发 
1. 引言 
这是专栏的第一篇文章我们将从环境准备、示例代码运行和详解三个方面带你快速入门 eBPF 开发。 读完这篇文章你将学会 ✔️ 如何用 Go  libbpfgo 开发 eBPF 程序。 ✔️ 如何编写、编译、运行 eBPF 代码。 ✔️ 掌握 eBPF 事件处理的工作原理。 ✔️ 完整可运行的 eBPF 示例代码(持续更新)。 
1.1 eBPF 简介 
eBPFExtended Berkeley Packet Filter是一项革命性的Linux内核技术它允许在不修改内核代码的情况下把用户自定义的代码插入到内核中运行不仅如此使用eBPFuprobe你甚至可以把自定义的代码插入到其它任意应用程序中。想象一下吧这意味着你几乎可以做任何事情尤其是在安全领域 
现在 eBPF 被广泛应用于以下领域包括但不限于 
网络监控如 Cilium 等项目利用 eBPF 实现高效的网络数据包处理。安全审计可以用来拦截系统调用实现进程级别的安全策略。性能分析eBPF 允许深入内核内部分析 I/O、调度、内存等性能指标。 
1.2 为何选择 Go  libbpfgo 
下表对比了常见的 eBPF 开发框架 
开发框架语言依赖部署复杂度性能优点缺点BCCPython  C需要 Python 运行环境复杂中等生态成熟大量示例和工具支持依赖 Python部署复杂性能较低libbpfC无额外依赖简单高官方推荐性能最佳适合生产环境开发难度高需要熟悉 C 语言libbpfgoGo  C依赖 libbpf简单高Go 语言封装Go 生态友好, 开发效率高依赖cgo调用 libbpfcilium/ebpfGo  C纯 Go 实现无需 libbpf简单高无 libbpf 依赖Go 生态友好功能覆盖较 libbpf 少rust-bpfRust需要 Rust toolchain复杂高安全性强Rust 生态Rust eBPF 生态尚不成熟工具链复杂 推荐选择 
快速验证原型 ➝ BCC最高性能  生产环境 ➝ libbpfGo 生态  轻量部署 ➝ cilium/ebpfGo 生态  libbpf 兼容 ➝ libbpfgoRust 生态  安全性优先 ➝ rust-bpf libbpfgo 是libbpf的Go语言绑定, 拥有官方libbpf的功能同时兼顾了 Go语言的易用性和生态非常适合快速开发和生产环境使用。 如果你没有Go语言基础也没关系, Go语言的代码非常简单易懂, 有C语言基础的同学也可以快速上手。 如果你也没有C语言基础, 那么本专栏可能不适合你 让我们开始吧 2. 环境准备 
为了确保你的 eBPF 代码能够顺利运行我们使用 Ubuntu 24.04 作为开发环境。 
2.1 依赖工具安装 
运行以下命令安装所需工具 
sudo apt update
sudo apt install -y clang llvm make git2.2 安装 Go 
确保你安装了 Go 1.22 及以上版本 
sudo apt install -y golang
go version  # 确保 Go 已正确安装3. 运行示例代码 
3.1 下载示例代码 
我们使用 cj-ebpf 这个示例项目, 这是专门为本专栏开发的ebpf实战项目 
git clone https://gitcode.com/weixin_47763623/cj-ebpf.git代码目录结构如下 
cj-ebpf/libbpfgo-eg
├── 000-hello  # hello world 示例代码
├── libbpf     # libbpf库源码
├── common     # ebpf常用函数封装
└── util       # go常用函数封装3.2 编译和运行 hello 示例 
进入 000-hello 目录 
cd cj-ebpf/libbpfgo-eg
go mod tidy  # 处理 Go 依赖
cd 000-hello
./build.sh   # 编译 eBPF 代码执行 eBPF 程序 
sudo ./bin/hello如果运行成功你应该会看到 eBPF 输出的日志。 
下面我们就从这个hello示例代码开始详细介绍 eBPF 程序的编写。 4. hello 示例代码详解 
这个示例的功能是, 通过跟踪 execve 系统调用, 监控所有进程的执行, 并把日志输出到终端。 
4.1 项目结构 
示例项目的结构如下 
000-hello
├── bin                   # 编译输出目录
│   ├── bpf.o             # eBPF 目标文件
│   └── hello             # 可执行文件
├── build.sh              # 编译脚本
└── src                   # 源码├── c                 # C 语言 BPF 代码│   ├── hello.bpf.c   # BPF 代码│   └── Makefile      # bpf 编译规则├── event.go          # Go 事件处理├── main.go           # Go 入口文件└── Makefile          # 顶层 Makefile, 编译Go程序和BPF程序1. bin/ - 编译输出目录 
bpf.ohello.bpf.c 编译后的 eBPF 目标文件由 clang 编译生成。hello最终的 Go 可执行文件由 Go 编译生成。 2. build.sh - 一键编译脚本 
负责调用 Makefile 编译 eBPF 和 Go 代码。 3. src/ - 源代码 c/ 目录存放 eBPF 代码C 语言。 hello.bpf.c核心 eBPF 逻辑代码定义 kprobe/tracepoint 等 BPF 处理逻辑。Makefile使用 clang 和 LLVM 工具链编译 BPF 代码。  event.go处理 BPF 事件如 perf buffer 读取、ring buffer 事件回调等。  main.go 加载 eBPF 程序 (hello.bpf.o)。注册事件监听 (perf buffer 或 ring buffer)。运行事件循环等待 BPF 事件触发并打印日志。  Makefile 顶层 Makefile先调用 src/c/Makefile 编译 BPF程序然后再编译 Go。  
4.1.1 顶层 Makefile 
这部分 Makefile 主要负责管理编译过程包括编译 C 语言程序、BPF 程序、以及 Go 程序的构建工作。整体的工作流程如下 
1. 基本配置与变量 
路径和工具链的配置 
SRC_ROOT  $(dir $(CURDIR)/)
OUTPUT  $(SRC_ROOT)/../../output
BIN  $(SRC_ROOT)/../binSRC_ROOT 是源代码的根目录。OUTPUT 和 BIN 分别是输出文件和可执行文件的路径。 
然后是应用的名称和 libbpf.a 的位置 
APP_NAME  hello
LIBBPF_OBJ  $(abspath $(OUTPUT)/libbpf.a)APP_NAME 指定最终生成的应用程序的名称。LIBBPF_OBJ 指定了 libbpf.a 静态库的位置。 
2. 编译选项 
编译和链接选项的设置 
CFLAGS  -ggdb -gdwarf -O2 -Wall -fpie -Wno-unused-variable -Wno-unused-functionCGO_CFLAGS_STATIC  -I$(abspath $(OUTPUT))
CGO_LDFLAGS_STATIC  -lelf -lz -lzstd $(LIBBPF_OBJ)
CGO_EXTLDFLAGS_STATIC  -w -extldflags -static 
CFLAGS 设置了编译器的常见选项包括调试信息和优化。对于 Go 程序CGO_CFLAGS_STATIC 和 CGO_LDFLAGS_STATIC 配置了静态编译的选项。 
3. 目标与规则 
.PHONY: all clean.PHONY 用于声明 make 的伪目标确保即使存在同名的文件也不会影响目标的执行。 
接下来是 all 目标即默认构建目标 
all: $(APP_NAME)默认目标是构建 hello 应用程序。 
构建 hello 应用程序的规则如下 
$(APP_NAME):$(MAKE) -C ./c buildCC$(CLANG) \CGO_CFLAGS$(CGO_CFLAGS_STATIC) \CGO_LDFLAGS$(CGO_LDFLAGS_STATIC) \GOARCH$(GOARCH) \go build \-tags netgo -ldflags $(CGO_EXTLDFLAGS_STATIC) \-o $(BIN)/$(APP_NAME) ./*.goecho build $(APP_NAME) success该规则首先通过 $(MAKE) -C ./c build 编译 BPF 程序。然后使用 clang 编译器和静态链接选项构建 Go 应用最终生成可执行文件 hello。 
4.1.2 ebpf的 Makefile 
该 Makefile 主要负责编译与构建 eBPF 程序确保所需的库、工具和头文件已经正确配置。 
1. 路径定义 
SRC_ROOT  $(dir $(CURDIR)/../)
PROJ_ROOT  $(SRC_ROOT)/../../
OUTPUT  $(SRC_ROOT)/../../output
BIN  $(SRC_ROOT)/../bin
LIBBPF  $(abspath $(SRC_ROOT)/../../libbpf)这些变量定义了项目的根目录、输出目录和 libbpf 库的路径。 LIBBPF 路径是指向 libbpf 的源代码所在位置。 
2. bpftool 和 vmlinux.h 配置 
BPFTOOL  $(shell which bpftool || /bin/false)
BTFFILE  /sys/kernel/btf/vmlinux
DBGVMLINUX  /usr/lib/debug/boot/vmlinux-$(shell uname -r)这部分检查系统中是否安装了 bpftool 工具并指定内核的 vmlinux.h 文件和调试版本的内核 vmlinux 文件路径。bpftool 是用来提取内核的 BTF (BPF Type Format) 信息的工具。 
3. 编译选项 
CFLAGS  -ggdb -gdwarf -O2 -Wall -fpie -Wno-unused-variable -Wno-unused-function -I$(abspath $(PROJ_ROOT))
LDFLAGS  这些是编译器的选项包括调试信息-ggdb -gdwarf、优化选项-O2、警告设置-Wall等。通过 -I 标志添加项目根目录到包含路径。 
4. 目标和规则 编译 bpf.o bpf.o: hello.bpf.c $(OUTPUT)/vmlinux.h$(CLANG) $(CFLAGS) -target bpf -D__TARGET_ARCH_x86 -I. -I$(OUTPUT) -c $ -o $(BIN)/$该规则编译 eBPF 程序 hello.bpf.c使用 clang 编译器和指定的编译选项。-target bpf 表示这是一个 eBPF 程序-D__TARGET_ARCH_x86 指定了目标架构。  编译 vmlinux.h $(OUTPUT)/vmlinux.h: 
ifeq ($(wildcard $(BPFTOOL)),)echo ERROR: could not find bpftoolexit 1
endif首先检查系统是否有 bpftool如果没有则报错。接着检查内核是否支持 BTF 格式并通过 bpftool 提取或生成 vmlinux.h 文件。  编译 libbpf libbpf: $(LIBBPF_STATIC)$(LIBBPF_STATIC): $(LIBBPF_SRC) $(wildcard $(LIBBPF_SRC)/*.[ch]) | $(OUTPUT)/libbpfCC$(CC) CFLAGS$(CFLAGS) LD_FLAGS$(LDFLAGS) \$(MAKE) -C $(LIBBPF_SRC) \BUILD_STATIC_ONLY1 \OBJDIR$(LIBBPF_OBJDIR) \DESTDIR$(LIBBPF_DESTDIR) \INCLUDEDIR LIBDIR UAPIDIR prefix libdir installlibbpf 库被单独编译为静态库libbpf.a。如果 libbpf 目录中的源文件有更新Makefile 会重新编译它。构建过程通过 make 命令在 libbpf 源码目录中进行。  4.2 eBPF 代码详解 
本节我们详细解析hello.bpf.c 这个 eBPF 代码文件它的作用是监听 execve 系统调用并将相关信息包括进程 pid、ppid、执行的文件名等发送到用户空间。 4.2.1 代码整体逻辑 
这段 eBPF 代码的主要功能是捕获 execve 系统调用并将进程相关信息上报到用户空间它的核心逻辑如下 
定义 perf 事件使用 BPF_MAP_TYPE_PERF_EVENT_ARRAY 来存储事件并供 eBPF 代码向用户空间发送数据。定义事件结构体event_t 结构体存储 execve 事件的相关信息包括进程 pid、父进程 ppid、进程名称 comm、执行的文件名 filename 等。跟踪 execve 系统调用使用 tracepoint 机制监听 sys_enter_execve当 execve 发生时获取相关进程信息并存入 event_t 结构体。读取参数通过 bpf_probe_read_user_str 读取 execve 调用的第一个参数即 filename确保能够正确读取用户空间字符串。发送事件到用户空间使用 bpf_perf_event_output 将事件数据发送到 perf 事件数组供用户空间的 BPF 程序读取和处理。 4.2.2 代码细节解析 
接下来我们对代码进行详细拆解。 
1️⃣ 头文件  许可证 
#include vmlinux.h
#include bpf/bpf_helpers.h
#include bpf/bpf_tracing.h
#include bpf/bpf_core_read.hchar _license[] SEC(license)  GPL;代码包含 bpf_helpers.h、bpf_tracing.h 和 bpf_core_read.h分别提供 BPF 辅助函数、tracepoint 相关定义和 BPF 内核数据访问函数。_license 变量用于指定 eBPF 程序的许可证这里声明为 GPL确保内核可以加载该 eBPF 代码。 2️⃣ 定义 perf 事件 
struct {__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);__uint(key_size, sizeof(u32));__uint(value_size, sizeof(u32));
} events  SEC(.maps);这里定义了 BPF_MAP_TYPE_PERF_EVENT_ARRAY用于存储 perf 事件允许 BPF 程序向用户空间发送数据。该 map 在 bpf_perf_event_output 函数中被使用。 3️⃣ 事件结构体 
#define FILE_NAME_MAX 256struct event_t {pid_t ppid;pid_t pid;int ret;char comm[16];char filename[FILE_NAME_MAX];
};event_t 结构体用于存储 execve 事件的信息包括 ppid执行 execve 的进程的父进程 ID。pid执行 execve 的进程 ID。comm进程名称最大长度 16与 task_struct 结构体中的 comm 字段一致。filenameexecve 执行的文件路径最大长度 256。  4️⃣ execve 事件跟踪 
SEC(tp/syscalls/sys_enter_execve)
int trace_execve(struct trace_event_raw_sys_enter *ctx) {SEC(tp/syscalls/sys_enter_execve) 定义了 eBPF 代码的 tracepoint绑定到 sys_enter_execve 事件即在进程执行 execve 之前触发。该 tracepoint 的参数 ctx 是 sys_enter_execve 事件的 trace_event_raw_sys_enter 结构体它包含系统调用的参数信息。 5️⃣ 读取进程信息 
struct event_t event  { 0, };
struct task_struct *task;task  (struct task_struct*)bpf_get_current_task();这里定义 event 结构体用于存储事件数据并初始化为 0。使用 bpf_get_current_task() 获取当前 task_struct这是内核中表示进程的结构体。 6️⃣ 读取 pid  ppid 
event.ppid  (pid_t)BPF_CORE_READ(task, real_parent, tgid);
event.pid  bpf_get_current_pid_tgid()  32;BPF_CORE_READ(task, real_parent, tgid) 通过 BPF 辅助函数读取当前进程的父进程 IDppid。bpf_get_current_pid_tgid() 获取当前进程的 pid 和 tgid其中高 32 位是 pid低 32 位是 tgid所以右移 32 位得到 pid。 7️⃣ 读取进程名称 
bpf_get_current_comm(event.comm, sizeof(event.comm));bpf_get_current_comm() 读取当前进程的名称并存入 event.comm名称最大长度为 16。 8️⃣ 读取 execve 文件名 
bpf_probe_read_user_str(event.filename, sizeof(event.filename), (char *)ctx-args[0]);ctx-args[0] 是 execve 调用的第一个参数即 filename需要读取的可执行文件路径。bpf_probe_read_user_str() 用于安全地从用户空间读取字符串并存入 event.filename。 ⚠️ 早期代码可能使用 BPF_CORE_READ(ctx, args[0])但 bpf_probe_read_user_str() 更安全能确保字符串正确终止避免越界读取。 9️⃣ 发送事件到用户空间 
bpf_perf_event_output(ctx, events, BPF_F_CURRENT_CPU, event, sizeof(event));bpf_perf_event_output() 将 event 结构体中的数据发送到 perf 事件数组 events供用户空间程序接收。BPF_F_CURRENT_CPU 表示数据写入当前 CPU 绑定的 perf 事件队列。 返回值 
return 0;eBPF 程序必须返回 int这里返回 0表示处理完 execve 事件不干涉系统行为。 4.2.3 小结 
✅ 这段 eBPF 代码的核心功能是监听 execve 调用并将进程相关信息上报。 ✅ 代码逻辑捕获事件 → 读取进程信息 → 读取 execve 参数 → 发送事件到用户空间。 ✅ 关键技术点 
使用 tracepoint 监听 sys_enter_execve 使用 BPF_CORE_READ 读取进程 ppid ️使用 bpf_probe_read_user_str() 读取用户空间数据 使用 bpf_perf_event_output() 发送事件  
这样我们就能在用户空间监听 execve 事件并收集相关进程信息 。 4.3 入口 main.go 
下面我们就来详细看一下用户空间的 Go 代码。 
在这一部分我们将逐行分析main.go的代码理解程序的整体逻辑并深入探讨其中的关键细节。 
4.3.1 代码整体逻辑 
main.go的目的是加载并运行一个eBPF程序通过perf buffer接收和处理事件同时监听退出信号来优雅地关闭程序。具体来说程序执行的流程如下 
信号处理程序会注册信号处理函数监听SIGINT中断信号和SIGTERM终止信号。当接收到这些信号时程序将优雅地退出。加载eBPF程序通过util.BpfLoadAndAttach加载指定的eBPF目标文件bpf.o并附加到内核中。初始化perf buffer创建并初始化perf buffer用于接收eBPF程序生成的事件。处理事件程序进入事件处理循环持续监听perf buffer中的事件并打印相应的日志直到收到退出信号。退出在收到退出信号后程序会打印退出日志并结束。 
4.3.2 代码细节解析 
1. 信号处理 
ctx, stop : signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()这段代码使用了signal.NotifyContext来创建一个可以监听系统信号SIGINT 和 SIGTERM的上下文ctx。当接收到这些信号时ctx会被取消。defer stop() 确保在main函数退出时取消信号监听避免资源泄漏。 
2. 日志设置 
log.SetLevel(log.DebugLevel)
log.Debug(load bpf program)这两行代码使用logrus包设置日志级别为Debug并记录一条调试日志表明正在加载BPF程序。log.Debug 是一种低级别的日志记录通常用于开发过程中帮助调试。 
3. 加载BPF程序 
bpfModule, err : util.BpfLoadAndAttach(bpf.o)
if err ! nil {log.Fatalf(%v, err)
}
defer bpfModule.Close()util.BpfLoadAndAttach(bpf.o) 会加载指定的eBPF程序此处为bpf.o并将其附加到系统中。如果加载失败程序会记录错误并退出。defer bpfModule.Close() 确保在程序退出时关闭eBPF模块并释放资源。 
4. 创建perf buffer 
eventsChannel : make(chan []byte)
lostChannel : make(chan uint64)
pb, err : bpfModule.InitPerfBuf(events, eventsChannel, lostChannel, 1024)
if err ! nil {return
}这里创建了两个通道eventsChannel 用于接收事件数据lostChannel 用于接收丢失的事件数量。bpfModule.InitPerfBuf 初始化了一个perf buffer该缓冲区会接收从eBPF程序生成的事件。1024 是缓冲区的大小表示最多可以缓存1024个事件。 
5. 启动perf buffer 
pb.Start()
defer pb.Close()pb.Start() 启动perf buffer开始接收事件。defer pb.Close() 确保在程序结束时关闭perf buffer。 
6. 事件处理 
processEvents(eventsChannel, lostChannel, ctx)程序进入processEvents函数开始循环接收并处理来自eventsChannel和lostChannel的事件直到收到退出信号。 
7. 事件处理函数 processEvents 
func processEvents(eventsChannel -chan []byte, lostChannel -chan uint64, ctx context.Context) {exit : falsefor {if exit {break}select {case data : -eventsChannel:var event Event// 解析事件数据并打印日志, 下文会详细介绍Event结构err : event.Parse(data)if err ! nil {log.Printf(parse event error: %v, err)} else {log.Printf(ppid: %d pid: %d comm[%s] filename[%s] ret%d, event.Ppid, event.Pid,event.CommString(), event.FilenameString(), event.Ret)}case n : -lostChannel:log.Printf(lost %d events, n)case -ctx.Done():exit  truebreak}}
}这个函数会持续监听eventsChannel和lostChannel中的数据。 当接收到事件数据时会解析并打印事件的详细信息如父进程IDppid、进程IDpid、进程名称comm、文件名filename和返回值ret。如果有丢失的事件则会打印丢失事件的数量。当接收到退出信号时ctx.Done()会设置exit为true从而退出循环。  
4.3.3 小结 
这一部分代码展示了如何使用Go语言和eBPF结合处理系统事件。它通过注册信号处理加载并附加eBPF程序使用perf buffer接收事件并通过一个事件处理函数打印事件信息。在程序退出时它会优雅地关闭资源。这个过程展示了eBPF在实际应用中的基础用法以及如何高效地进行事件处理。 
4.4 事件处理 event.go 
在这一小节中我们将详细解析处理 event 数据的代码。该代码的主要功能是定义了一个 Event 结构体并提供了一些方法来解析和转换与该结构体相关的数据。 
4.4.1 整体逻辑 
首先Event 结构体用于存储与某些事件相关的数据主要包含进程ID、父进程ID、返回值、进程名称Comm和文件名Filename。该结构体包含的方法用于将字节数组data转换成结构体字段并处理字符串字段的显示。整个过程分为以下几步 
定义数据结构Event 结构体包含多个字段其中有整型字段 Ppid、Pid 和 Ret以及用于存储字符串的 Comm 和 Filename 字段。转换字符串通过自定义方法 CommString 和 FilenameString将字节数组转换为更易读的字符串。解析字节数据通过 Parse 方法将传入的字节数据解析为 Event 结构体实例。 
4.4.2 代码细节解析 
接下来我们深入分析代码的每一部分。 
结构体定义 
type Event struct {Ppid     uint32Pid      uint32Ret      int32Comm     [16]byteFilename [256]byte
}这段代码定义了一个 Event 结构体包含五个字段 Ppid 和 Pid分别表示父进程ID和进程ID使用 uint32 类型存储。  Ret表示事件返回的值使用 int32 类型通常用于表示调用的返回状态或结果。  Comm存储进程名的字节数组长度为 16 字节。由于进程名可能较短因此使用固定大小的数组。  Filename存储文件名的字节数组长度为 256 字节用于存储与该事件相关的文件路径。  Comm 字段转换  
func (e *Event) CommString() string {return string(bytes.TrimRight(e.Comm[:], \x00))
}该方法将 Comm 字节数组转换为字符串并去除末尾的 \x00空字节。bytes.TrimRight 函数用于去除 Comm 字段中多余的填充字节。转换后的结果是一个不包含空字节的有效进程名。 
Filename 字段转换 
func (e *Event) FilenameString() string {return string(bytes.TrimRight(e.Filename[:], \x00))
}FilenameString 方法与 CommString 类似将 Filename 字节数组转换为字符串并去除末尾的空字节。这样便于获取该事件相关的文件路径。 
数据解析 
func (e *Event) Parse(data []byte) error {err : binary.Read(bytes.NewBuffer(data), binary.LittleEndian, e)if err ! nil {return err}return nil
}Parse 方法用于解析字节数据并填充 Event 结构体。这里使用 binary.Read 函数将 data 字节数据按照 LittleEndian 字节序解析到 Event 结构体中。LittleEndian 表示数据的低位字节存储在低地址中这是大多数 x86 系统采用的字节序。如果解析过程中发生错误将返回相应的错误信息。 
4.4.3 小结 
在这一段代码中我们定义了一个 Event 结构体并为其提供了转换和解析字节数据的方法。通过 Parse 方法我们可以将原始的字节流解析为结构体实例方便后续的处理。CommString 和 FilenameString 方法则帮助我们将字节数组转化为易于阅读的字符串去除多余的空字节。这个过程对于事件数据的处理至关重要确保了我们能够高效地提取出事件相关的关键信息。 4.5 小结 
通过这个hello示例代码我们展示了如何使用eBPF捕获内核事件如execve系统调用并通过perf buffer将事件数据传递给用户空间进行处理。在用户空间中Go程序则负责加载和运行eBPF程序并实现事件的捕获与处理逻辑。 
关键步骤包括 
eBPF程序捕获execve事件读取相关进程信息如pid、ppid、进程名称和文件路径并通过perf buffer发送到用户空间。用户空间通过Go程序加载eBPF程序初始化perf buffer并在事件循环中处理来自内核的事件数据。 
这种模式将内核事件捕获与用户空间处理结合起来使得开发者可以高效地监控和响应内核级事件非常适用于安全审计、性能监控等场景。 
5. 总结与延伸阅读 
5.1 关键知识点回顾 
✅ eBPF 允许在内核中运行用户定义的代码。 ✅ libbpfgo 提供了一种高效的 Go 语言 eBPF 交互方式。 ✅ eBPF 代码通常分为 BPF 程序 和 用户态 Go 代码。 
5.2 进一步学习 推荐阅读 
《BPF Performance Tools》eBPF 进阶教程官方 libbpf 文档 现在你已经完成了 Go  libbpfgo 的 eBPF 开发入门请持续关注我的eBPF实战专栏我们将不断更新更多有关 eBPF 的内容。 文章转载自: http://www.morning.dycbp.cn.gov.cn.dycbp.cn http://www.morning.mzmqg.cn.gov.cn.mzmqg.cn http://www.morning.rxtxf.cn.gov.cn.rxtxf.cn http://www.morning.ptzf.cn.gov.cn.ptzf.cn http://www.morning.njdtq.cn.gov.cn.njdtq.cn http://www.morning.znqxt.cn.gov.cn.znqxt.cn http://www.morning.cnqdn.cn.gov.cn.cnqdn.cn http://www.morning.rkmsm.cn.gov.cn.rkmsm.cn http://www.morning.qtfss.cn.gov.cn.qtfss.cn http://www.morning.xlwpz.cn.gov.cn.xlwpz.cn http://www.morning.jyfrz.cn.gov.cn.jyfrz.cn http://www.morning.jqpyq.cn.gov.cn.jqpyq.cn http://www.morning.bmrqz.cn.gov.cn.bmrqz.cn http://www.morning.psxfg.cn.gov.cn.psxfg.cn http://www.morning.wjplm.cn.gov.cn.wjplm.cn http://www.morning.qckwj.cn.gov.cn.qckwj.cn http://www.morning.mnrqq.cn.gov.cn.mnrqq.cn http://www.morning.nzcys.cn.gov.cn.nzcys.cn http://www.morning.psxfg.cn.gov.cn.psxfg.cn http://www.morning.nqgjn.cn.gov.cn.nqgjn.cn http://www.morning.zrjzc.cn.gov.cn.zrjzc.cn http://www.morning.zkdmk.cn.gov.cn.zkdmk.cn http://www.morning.csnmd.cn.gov.cn.csnmd.cn http://www.morning.wspyb.cn.gov.cn.wspyb.cn http://www.morning.ryxgk.cn.gov.cn.ryxgk.cn http://www.morning.bpmfl.cn.gov.cn.bpmfl.cn http://www.morning.fjzlh.cn.gov.cn.fjzlh.cn http://www.morning.qkqjz.cn.gov.cn.qkqjz.cn http://www.morning.sjsks.cn.gov.cn.sjsks.cn http://www.morning.lpsjs.com.gov.cn.lpsjs.com http://www.morning.wpxfk.cn.gov.cn.wpxfk.cn http://www.morning.tmcmj.cn.gov.cn.tmcmj.cn http://www.morning.amonr.com.gov.cn.amonr.com http://www.morning.rpth.cn.gov.cn.rpth.cn http://www.morning.cmldr.cn.gov.cn.cmldr.cn http://www.morning.wyfpc.cn.gov.cn.wyfpc.cn http://www.morning.tsdjj.cn.gov.cn.tsdjj.cn http://www.morning.kqglp.cn.gov.cn.kqglp.cn http://www.morning.frxsl.cn.gov.cn.frxsl.cn http://www.morning.chehb.com.gov.cn.chehb.com http://www.morning.wfpmt.cn.gov.cn.wfpmt.cn http://www.morning.fkgqn.cn.gov.cn.fkgqn.cn http://www.morning.knngw.cn.gov.cn.knngw.cn http://www.morning.pthmn.cn.gov.cn.pthmn.cn http://www.morning.nfqyk.cn.gov.cn.nfqyk.cn http://www.morning.thrgp.cn.gov.cn.thrgp.cn http://www.morning.ybmp.cn.gov.cn.ybmp.cn http://www.morning.dmlsk.cn.gov.cn.dmlsk.cn http://www.morning.qlck.cn.gov.cn.qlck.cn http://www.morning.jbtwq.cn.gov.cn.jbtwq.cn http://www.morning.hgcz.cn.gov.cn.hgcz.cn http://www.morning.bnylg.cn.gov.cn.bnylg.cn http://www.morning.csznh.cn.gov.cn.csznh.cn http://www.morning.yrfxb.cn.gov.cn.yrfxb.cn http://www.morning.yxnkr.cn.gov.cn.yxnkr.cn http://www.morning.wtrjq.cn.gov.cn.wtrjq.cn http://www.morning.nqbs.cn.gov.cn.nqbs.cn http://www.morning.jbpdk.cn.gov.cn.jbpdk.cn http://www.morning.hwlmy.cn.gov.cn.hwlmy.cn http://www.morning.qgxnw.cn.gov.cn.qgxnw.cn http://www.morning.mbmtn.cn.gov.cn.mbmtn.cn http://www.morning.lgcqj.cn.gov.cn.lgcqj.cn http://www.morning.cwqln.cn.gov.cn.cwqln.cn http://www.morning.nbybb.cn.gov.cn.nbybb.cn http://www.morning.nwnbq.cn.gov.cn.nwnbq.cn http://www.morning.crkmm.cn.gov.cn.crkmm.cn http://www.morning.ymdhq.cn.gov.cn.ymdhq.cn http://www.morning.mhbcy.cn.gov.cn.mhbcy.cn http://www.morning.cnqff.cn.gov.cn.cnqff.cn http://www.morning.kcnjz.cn.gov.cn.kcnjz.cn http://www.morning.qmbtn.cn.gov.cn.qmbtn.cn http://www.morning.rdfq.cn.gov.cn.rdfq.cn http://www.morning.ffrys.cn.gov.cn.ffrys.cn http://www.morning.hmdn.cn.gov.cn.hmdn.cn http://www.morning.fgxnb.cn.gov.cn.fgxnb.cn http://www.morning.lgqdl.cn.gov.cn.lgqdl.cn http://www.morning.nlgmr.cn.gov.cn.nlgmr.cn http://www.morning.flfdm.cn.gov.cn.flfdm.cn http://www.morning.lgpzq.cn.gov.cn.lgpzq.cn http://www.morning.kpyyf.cn.gov.cn.kpyyf.cn