You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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";

关键细节说明

  1. BPF_KSYSCALL宏的正确用法:
    宏的第一个参数是你的eBPF程序名称(比如这里的entry_read),后续参数要严格匹配目标系统调用的签名。sys_read的标准签名是ssize_t sys_read(int fd, char __user *buf, size_t count),所以把count的类型从int改成size_t更严谨,避免类型不匹配引发的内核验证问题。

  2. PID获取修正:
    bpf_get_current_pid_tgid()返回的64位值中,低32位是进程ID(PID),高32位是线程组ID(TGID)。如果要以PID作为哈希映射的key,直接取低32位即可。

  3. libbpf版本适配:
    你的libbpf版本是0.5.0,完全支持BPF_KSYSCALL宏的自动节生成,编译时确保链接正确的libbpf库即可。

内容的提问来源于stack exchange,提问作者ObiWanKnewby

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 20:23:17