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

使用perf_event_open+mmap环形缓冲区时,如何定义内核返回的结构类型?

理清perf_event_open环形缓冲区的记录结构控制逻辑

我来帮你拆解这个问题——这确实是perf_event_open里容易踩坑的点,尤其是刚上手做周期性采集的时候。

核心:所有记录都以perf_event_header开头

不管你配置的是什么事件类型,环形缓冲区里的每一条记录必然以struct perf_event_header作为起始。这个结构体里的type字段是关键,它直接告诉你这条记录属于什么类型(比如采样记录、MMAP映射记录、进程名称变更记录等),你需要先解析这个字段,再去匹配对应的具体结构。

struct perf_event_header {
    u32 type;       // 记录类型,比如PERF_RECORD_SAMPLE、PERF_RECORD_MMAP等
    u16 misc;       // 辅助标记,比如是否是内核态事件
    u16 size;       // 整条记录的总大小
};

控制返回结构类型的perf_event_attr关键成员

你要的“控制返回结构类型”的配置,主要集中在perf_event_attr的这几个成员上:

1. sample_type(最核心)

这个字段是一个位掩码,决定了**采样记录(PERF_RECORD_SAMPLE)**里包含哪些数据维度。比如你想记录进程ID、时间戳、CPU编号,就可以设置:

attr.sample_type = PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU;

不同的位掩码组合,对应采样记录在perf_event_header之后的结构会完全不同。比如上面的组合,后续数据就是:

// 紧跟perf_event_header之后的采样数据
struct {
    u32 pid, tid;   // 对应PERF_SAMPLE_TID
    u64 time;       // 对应PERF_SAMPLE_TIME
    u32 cpu, res;   // 对应PERF_SAMPLE_CPU
};

常见的sample_type位包括PERF_SAMPLE_CALLCHAIN(调用栈)、PERF_SAMPLE_BRANCH_STACK(分支记录)、PERF_SAMPLE_RAW(原始硬件事件数据)等。

2. read_format

如果你用PERF_EVENT_IOC_READ命令读取事件,或者设置了水位触发/频率触发的周期性读取,这个字段控制**读取记录(PERF_RECORD_READ)**的格式。比如你想同时拿到总计数、时间戳、CPU编号,就设置:

attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TIME | PERF_FORMAT_CPU;

对应的PERF_RECORD_READ结构会包含这些字段。

3. branch_sample_type

只有当sample_type包含PERF_SAMPLE_BRANCH_STACK时,这个字段才生效。它是另一个位掩码,控制分支记录的细节:比如是否记录用户态分支、内核态分支、调用/返回路径、异常跳转等。对应的结构是struct perf_branch_entry,字段会根据这个掩码变化。

4. 辅助过滤字段(间接影响记录内容)

比如exclude_user、exclude_kernel、exclude_hv这些字段,它们不会改变记录的结构类型,但会过滤掉特定场景的事件,间接影响你拿到的记录数量和内容。

如何匹配记录类型与对应结构体

拿到环形缓冲区的数据后,流程是这样的:

  1. 先读取perf_event_header,通过type判断记录类型;
  2. 如果是元数据记录(比如PERF_RECORD_MMAP、PERF_RECORD_COMM、PERF_RECORD_EXIT等),这些结构是固定的,直接用内核头文件里对应的结构体解析即可(比如struct perf_record_mmap);
  3. 如果是采样记录(PERF_RECORD_SAMPLE),根据你之前设置的sample_type掩码,逐个解析对应的字段;
  4. 如果是读取记录(PERF_RECORD_READ),根据read_format掩码解析对应的字段。

实用提示

  • 一定要参考你当前运行内核版本的linux/perf_event.h头文件——不同内核版本的perf结构可能有细微变化(比如某些字段的长度、新增的位掩码);
  • 可以先做小范围测试:比如只设置PERF_SAMPLE_TID,然后打印解析出的pid/tid,验证结构是否正确,再逐步添加更多sample_type位;
  • 如果用perf record命令生成数据,再用perf script解析,可以反向验证你的结构解析是否正确——perf工具本身就是基于perf_event_open实现的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 18:07:43