使用BPF_KSYSCALL编写eBPF程序时遇标识符错误求助
BPF_KSYSCALL宏使用错误的修复方案
核心问题
你犯了两个关键错误:
- 同时手动添加
SEC("kprobe/sys_read")注解和使用BPF_KSYSCALL宏,二者冲突导致编译报错。BPF_KSYSCALL宏内部已经自动生成了对应系统调用的kprobe入口节定义,不需要额外加SEC。 - 哈希映射
active_read_args_map的value类型定义为__u64,但实际要存储的是struct data_args_t结构体,类型不匹配会导致后续映射操作失败。
修正后的完整BPF程序
#include <linux/bpf.h> #include <bpf/bpf_tracing.h> #include <bpf/bpf_helpers.h> struct data_args_t { int fd; const char* buf; }; struct { __uint(type, BPF_MAP_TYPE_HASH); __type(key, __u32); __type(value, struct data_args_t); // 修正value类型为对应结构体 __uint(max_entries, 100); } active_read_args_map SEC(".maps"); // 直接使用BPF_KSYSCALL宏,无需额外SEC注解 int BPF_KSYSCALL(entry_read, int fd, char* buf, size_t count) { // 获取当前进程PID(bpf_get_current_pid_tgid返回u64,低32位是PID) __u32 id = (__u32)bpf_get_current_pid_tgid(); struct data_args_t read_args = {}; read_args.fd = fd; read_args.buf = buf; bpf_map_update_elem(&active_read_args_map, &id, &read_args, BPF_NOEXIST); return 0; } char __license[] SEC("license") = "Dual MIT/GPL";
关键细节说明
BPF_KSYSCALL宏的正确用法:
宏的第一个参数是你的eBPF程序名称(比如这里的entry_read),后续参数要严格匹配目标系统调用的签名。sys_read的标准签名是ssize_t sys_read(int fd, char __user *buf, size_t count),所以把count的类型从int改成size_t更严谨,避免类型不匹配引发的内核验证问题。PID获取修正:
bpf_get_current_pid_tgid()返回的64位值中,低32位是进程ID(PID),高32位是线程组ID(TGID)。如果要以PID作为哈希映射的key,直接取低32位即可。libbpf版本适配:
你的libbpf版本是0.5.0,完全支持BPF_KSYSCALL宏的自动节生成,编译时确保链接正确的libbpf库即可。
内容的提问来源于stack exchange,提问作者ObiWanKnewby
相关产品推荐
相关产品推荐

