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

eBPF CO:RE开发vmlinux.h缺失内容及tracepoint参数结构异常问题

eBPF CO:RE tracepoint开发问题解答

1. tracepoint入参获取、vmlinux.h相关疑问

vmlinux.h核心作用

vmlinux.h是通过内核BTF(类型元数据)导出的全量内核内部类型、函数、常量的C头文件,是eBPF CO:RE(一次编译多内核运行)能力的核心依赖:CO:RE靠vmlinux.h里的类型信息,自动在加载时适配不同内核版本的结构体成员偏移,无需开发者手动做版本兼容。

为什么vmlinux.h没有sys_enter_kill的tracepoint参数结构体定义

tracepoint的入参结构体是内核trace子系统动态生成的内部类型,默认不会收录到内核公开的BTF信息中,因此bpftool导出vmlinux.h时无法抓取到这类结构体的定义。

tracepoint入参的正确获取方式

无需手动定义结构体,直接使用libbpf提供的BPF_TRACEPOINT_SYSCALL*系列辅助宏即可直接拿到入参,自动处理偏移读取和兼容性问题。

2. BPF_F_CURRENT_CPU宏缺失、vmlinux.h与uapi头文件共存问题

vmlinux.h和uapi/linux/bpf.h可以同时引入,只要严格遵守引入顺序:先引入vmlinux.h,再引入uapi头文件即可,避免uapi的公开类型定义和vmlinux.h里的内核类型定义冲突。
BPF_F_CURRENT_CPU属于UAPI层面的公共宏,不属于内核内部类型,因此不会导出到vmlinux.h中,你代码中手动定义该宏的方式是合法可用的。

3. 参照tracepoint format定义结构体异常的原因

这是syscall类tracepoint的经典对齐问题:
syscall tracepoint的入参字段是按64位系统字长对齐存储的,你从/sys/kernel/debug/tracing拿到的format里的size是字段本身的大小,offset是对齐后的实际存储偏移:

field:int __syscall_nr; offset:8;   size:4; signed:1;
field:pid_t pid;    offset:16;  size:8; signed:0;

可以看到__syscall_nr本身只占4字节,但是和下一个pid字段的偏移差了8字节,中间有4字节的对齐填充。你按format给的字段类型(int)定义结构体时,C编译器的对齐规则和内核tracepoint的对齐规则不匹配,导致后续所有字段的偏移全部错位,所以无法正常运行。
你改用long类型(64位系统下占8字节)定义这几个字段后,刚好匹配了对齐后的偏移,因此可以正常读取参数。
此外你代码中BPF_CORE_READ不生效的原因是你自定义的结构体没有对应的BTF信息,CO:RE无法对自定义类型做偏移重定位,因此无法正常读取字段值。

最优修复方案

不要手动定义tracepoint入参结构体,直接使用libbpf提供的辅助宏,自动处理对齐和兼容性问题:

SEC("tracepoint/syscalls/sys_enter_kill")
int BPF_TRACEPOINT_SYSCALL3(sys_enter_kill, pid_t, pid, int, sig, int, reserved)
{
    // 直接使用pid、sig变量即可,无需手动处理偏移
    if (sig != 9)
        return 0;
    // 后续业务逻辑
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 01:15:02