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

为何调用bpf_trace_printk会导致eBPF程序加载失败?

问题分析与解决方法

你的eBPF程序加载失败有两个核心原因:

  1. 直接使用全局可写变量counter,eBPF验证器禁止这种操作
  2. 全局变量的非法访问导致后续bpf_printk的调用验证失败

修复后的代码

#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>

// 用BPF数组映射存储计数器,替代全局变量
struct {
    __uint(type, BPF_MAP_TYPE_ARRAY);
    __uint(max_entries, 1);
    __type(key, int);
    __type(value, int);
} counter_map SEC(".maps");

SEC("xdp")
int hello(void *ctx)
{
    int key = 0;
    // 从映射中获取计数器指针
    int *counter = bpf_map_lookup_elem(&counter_map, &key);
    
    // 空指针检查,避免验证器报错
    if (!counter)
        return XDP_PASS;

    bpf_printk("Hello World %d", *counter);
    (*counter)++;
    return XDP_PASS;
}

char LICENSE[] SEC("license") = "Dual BSD/GPL";

关键修复点说明

  • 替换全局变量为BPF映射:eBPF程序不能直接修改全局可写变量,必须通过BPF映射(map)来管理状态。这里用BPF_MAP_TYPE_ARRAY类型的映射,仅存储一个整数值作为计数器。
  • 空指针检查:调用bpf_map_lookup_elem必须检查返回值,否则eBPF验证器会认为存在非法内存访问风险,拒绝加载程序。
  • 正确使用bpf_printk:修复全局变量问题后,bpf_printk的调用会自动通过验证,无需额外修改。

编译与加载步骤

  1. 编译程序:
clang -target bpf -D__TARGET_ARCH_x86_64 -I/usr/include/linux -I/usr/include/x86_64-linux-gnu -O2 -c hello.bpf.c -o hello.bpf.o
  1. 加载程序(若存在BTF问题,添加--no-btf参数):
bpftool prog load hello.bpf.o /sys/fs/bpf/hello --no-btf
  1. 查看输出:
cat /sys/kernel/debug/tracing/trace_pipe

额外说明

若仍然遇到btf_vmlinux is malformed错误,检查内核是否开启了BTF支持(CONFIG_DEBUG_INFO_BTF=y)。如果内核未开启BTF,加载时必须添加--no-btf参数跳过BTF验证。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 08:17:31