为何bpf_perf_event_output返回-22?BPF程序TCP RTT采集异常
排查BPF程序
bpf_perf_event_output返回-22(EINVAL)问题 核心错误分析
返回-22对应EINVAL(无效参数),结合你挂钩tcp_rcv_established的场景,以下是针对性排查方向:
1. Perf Event Map定义错误
- 必须确保map类型为
BPF_MAP_TYPE_PERF_EVENT_ARRAY,若误定义为BPF_MAP_TYPE_HASH等其他类型,直接触发该错误。 - 检查map参数:
key_size需为4(对应CPU ID长度),value_size需为4(对应perf event fd长度),max_entries至少等于系统CPU核心数。
2. 用户态Perf Map初始化缺失
- 用户态必须为每个CPU创建perf event,并将有效fd写入map对应CPU索引位置。若遗漏此步骤或写入无效fd,BPF程序调用时会返回EINVAL。
- 查看strace日志中的
bpf(BPF_MAP_UPDATE_ELEM)调用:确认key为合法CPU编号,value为有效perf event fd,flags设为0。若该调用返回-1,说明初始化流程出错。
3. bpf_perf_event_output参数错误
- 第一个参数必须是kprobe场景下的
struct pt_regs *上下文,传参错误(如NULL或其他结构体)会触发EINVAL。 - 第二个参数需为用户态传入的合法perf map fd,BPF程序中需通过全局变量或
bpf_map_lookup_elem正确引用。 - 事件大小不能超过用户态perf event设置的page限制(通常4096字节),过大也会导致无效参数错误。
4. 内核版本兼容性问题
- 不同内核版本对kprobe上下文、perf event规则有差异:
- 4.15之前内核的
pt_regs结构定义不同,可能导致上下文传递错误。 - 5.8+内核需确保用户态进程持有
CAP_PERFMON权限,否则perf event创建失败。
- 4.15之前内核的
- 对比不同内核的strace日志,重点看
perf_event_open、bpf(BPF_PROG_LOAD)的返回值,定位版本差异导致的初始化失败。
5. 内核配置与权限问题
- 确认内核开启
CONFIG_BPF=y、CONFIG_BPF_SYSCALL=y、CONFIG_PERF_EVENTS=y、CONFIG_KPROBES=y等必要选项。 - 运行程序的用户需持有
CAP_BPF、CAP_PERFMON(5.8+)或CAP_SYS_ADMIN权限,否则会间接导致map或perf event初始化失败。
结合你的资源排查建议
- 核对两段BPF代码中的perf map定义,确认类型、参数完全符合要求。
- 查看
trace_pipe输出:若没有BPF程序的打印日志(如bpf_trace_printk输出),说明kprobe挂载失败,需先解决挂载问题。 - 对比不同内核的strace日志,定位
bpf(BPF_MAP_CREATE)、perf_event_open、bpf(BPF_MAP_UPDATE_ELEM)等关键调用的错误点。 - 简化BPF程序至最小可复现版本:仅输出固定大小的简单结构体,排除复杂事件结构导致的参数错误。
内容的提问来源于stack exchange,提问作者dcy
相关产品推荐
相关产品推荐

