bpf中的数据结构bpf_perf_event_data解析

发布时间 2023-07-08 08:43:43作者: 温暖的电波

1 前言

在系统性能运维监控的一些场景中我们往往需要对系统进行"采样"分析,最场景的例子就是perf top/record;在使用ebpf+perf event的情况下,ebpf中使用SEC("perf_event")这个名字的section来作为perf event的prog程序。 这类程序有着固定的参数类型:struct bpf_perf_event_data,如下所示:

SEC("perf_event")
int perf_event_foo(struct bpf_perf_event_data *ctx)

这个参数是什么含义呢?里面有什么成员呢?这些问题都是本文要讲究的内容。

2 结构体的构成

这里的参数ctx是struct bpf_perf_event_data结构:

struct bpf_perf_event_data {
        bpf_user_pt_regs_t regs;
        __u64 sample_period;
        __u64 addr;
};

 

可以看到这个结构的第一个参数是bpf_user_pt_regs_t结构,这个结构对于不同的架构,定义不同。这里仅举x86和arm64为例进行说明(其他架构大部分都和x86或者arm64类似)。

2.1 x86架构

typedef struct pt_regs bpf_user_pt_regs_t;

 

对于x86架构而言bpf_user_pt_regs_t就等价于struct pt_regs结构,也就是Linux中存放寄存器上下文的结构。

2) arm64架构

typedef struct user_pt_regs bpf_user_pt_regs_t;

 

对于arm64架构而言,user_pt_regs的定义,以及与上下文寄存器struct pt_regs的关联如下:

/* user_pt_regs中包含了上下文切换所需要的绝大部分信息 */
truct user_pt_regs {
        __u64           regs[31];
        __u64           sp;
        __u64           pc;
        __u64           pstate;
};

struct pt_regs {
        union {
                /* user_pt_regs作为第一个成员放到pt_regs中 */
                struct user_pt_regs user_regs;
                struct {
                        u64 regs[31];
                        u64 sp;
                        u64 pc;
                        u64 pstate;
                };
        };
        u64 orig_x0;
#ifdef __AARCH64EB__
        u32 unused2;
        s32 syscallno;
#else
        s32 syscallno;
        u32 unused2;
#endif

        u64 orig_addr_limit;
        /* Only valid when ARM64_HAS_IRQ_PRIO_MASKING is enabled. */
        u64 pmr_save;
        u64 stackframe[2];

        /* Only valid for some EL1 exceptions. */
        u64 lockdep_hardirqs;
        u64 exit_rcu;
};

 

 3 总结

我们了解了struct bpf_perf_event_data结构的构成,知道了它与struct pt_regs的关系,这对于我们对系统的探测、监控更加方便。