eBPF使用bpf_map_update_elem传内核态数据出现verifier错误如何解决
问题1:
R1 type=map_value expected=map_ptr错误原因与修复 该错误表示调用bpf_map_update_elem时,第一个入参需要是合法的BPF map指针,但内核验证器识别到传入的参数是普通全局变量,不是map指针,具体原因和修复方案如下:
- 原因1:你的BPF map没有指定正确的内核可识别段,内核仅会从
maps(或新版本的.maps)段加载map定义,普通全局变量不会被识别为BPF map。 - 原因2:你当前使用的Makefile多步编译流程会丢弃ELF文件中的自定义段,即使你给map加了
SEC("maps")注解,生成的目标文件里也没有对应段,内核加载时自然找不到map定义。
修复步骤
- 修改BPF代码的map定义,加上段注解:
// 老内核版本用SEC("maps") SEC("maps") struct bpf_map_def EVENTS = { .type = BPF_MAP_TYPE_HASH, .key_size = sizeof(__u32), .value_size = sizeof(__u32), .max_entries = 1, }; // 5.10+内核建议用更规范的BTF map定义,段注解为SEC(".maps") /* struct { __uint(type, BPF_MAP_TYPE_HASH); __uint(max_entries, 1); __type(key, __u32); __type(value, __u32); } EVENTS SEC(".maps"); */
- 修改Makefile的编译规则,使用clang原生BPF目标编译,避免丢段:
CLANG ?= clang ARCH ?= $(shell uname -m | sed -e 's/aarch64/arm64/' -e 's/x86_64/x86/') KERNEL ?= /usr/src/linux CFLAGS += \ -O2 -g \ -D__KERNEL__ \ -D__BPF_TRACING__ \ -Wno-unused-value \ -Wno-pointer-sign \ -Wno-compare-distinct-pointer-types \ -Wno-address-of-packed-member \ -Wno-tautological-compare \ -Wno-unknown-warning-option \ -Wno-gnu-variable-sized-type-not-at-end \ -fno-asynchronous-unwind-tables bytecode.$(ARCH).o: bytecode.c $(CLANG) -target bpf $(CFLAGS) -c $< -o $@
不需要走opt、llvm-dis、llc的多步管道编译,clang原生支持-target bpf参数直接生成合法的BPF ELF文件,会完整保留自定义段。
问题2:bpf_printk日志查看方法
bpf_printk的输出会写入内核trace缓冲区,有两种常用查看方式:
- 实时查看:执行
cat /sys/kernel/debug/tracing/trace_pipe,命令会持续阻塞,有新日志就会打印,按Ctrl+C退出。如果提示路径不存在,先执行mount -t debugfs none /sys/kernel/debug挂载debugfs。 - 离线查看:执行
dmesg命令,bpf_printk的输出也会同步到内核环形缓冲区,可直接通过dmesg过滤查看,缺点是日志量大时可能被覆盖。
内容的提问来源于stack exchange,提问作者Nimrodshn
相关产品推荐
相关产品推荐

