“perf_event_open”系统调用通过选项“PERF_RECORD_SAMPLE”返回的结构中的“id”和“stream_id”有啥区别?

Posted

技术标签:

【中文标题】“perf_event_open”系统调用通过选项“PERF_RECORD_SAMPLE”返回的结构中的“id”和“stream_id”有啥区别?【英文标题】:Whats the difference between "id" and "stream_id" in the structure returned with the option "PERF_RECORD_SAMPLE" by the "perf_event_open" syscall?“perf_event_open”系统调用通过选项“PERF_RECORD_SAMPLE”返回的结构中的“id”和“stream_id”有什么区别? 【发布时间】:2020-02-20 09:39:15 【问题描述】:

我正在尝试使用perf_event_open 系统调用编写一段代码。但我不明白我的内存映射中返回的结构中idstream_id 字段之间的真正区别。


这个结构是这样的(来自perf_event_open的手册页):

struct 
          struct perf_event_header header;
          u64    sample_id;   /* if PERF_SAMPLE_IDENTIFIER */
          u64    ip;          /* if PERF_SAMPLE_IP */
          u32    pid, tid;    /* if PERF_SAMPLE_TID */
          u64    time;        /* if PERF_SAMPLE_TIME */
          u64    addr;        /* if PERF_SAMPLE_ADDR */
          u64    id;          /* if PERF_SAMPLE_ID */
          u64    stream_id;   /* if PERF_SAMPLE_STREAM_ID */
          u32    cpu, res;    /* if PERF_SAMPLE_CPU */
          u64    period;      /* if PERF_SAMPLE_PERIOD */
          struct read_format v;
                                          /* if PERF_SAMPLE_READ */
          u64    nr;          /* if PERF_SAMPLE_CALLCHAIN */
          u64    ips[nr];     /* if PERF_SAMPLE_CALLCHAIN */
          u32    size;        /* if PERF_SAMPLE_RAW */
          char  data[size];   /* if PERF_SAMPLE_RAW */
          u64    bnr;         /* if PERF_SAMPLE_BRANCH_STACK */
          struct perf_branch_entry lbr[bnr];
                                          /* if PERF_SAMPLE_BRANCH_STACK */
          u64    abi;         /* if PERF_SAMPLE_REGS_USER */
          u64    regs[weight(mask)];
                                          /* if PERF_SAMPLE_REGS_USER */
          u64    size;        /* if PERF_SAMPLE_STACK_USER */
          char   data[size];  /* if PERF_SAMPLE_STACK_USER */
          u64    dyn_size;    /* if PERF_SAMPLE_STACK_USER &&
                                             size != 0 */
          u64    weight;      /* if PERF_SAMPLE_WEIGHT */
          u64    data_src;    /* if PERF_SAMPLE_DATA_SRC */
          u64    transaction; /* if PERF_SAMPLE_TRANSACTION */
          u64    abi;         /* if PERF_SAMPLE_REGS_INTR */
          u64    regs[weight(mask)];
                                          /* if PERF_SAMPLE_REGS_INTR */
          ;

手册页给了我这个解释:

id               If PERF_SAMPLE_ID is enabled, a 64-bit unique ID is included.  If the event is a member of an event group, the group leader ID is returned.  This ID is the same as the one returned by PERF_FORMAT_ID.
stream_id        If PERF_SAMPLE_STREAM_ID is enabled, a 64-bit unique ID is included. Unlike PERF_SAMPLE_ID the actual ID is returned, not the group leader.  This ID is the same as the one returned by PERF_FORMAT_ID.

但问题就在这里:文档似乎不连贯。

我错过了什么吗?

感谢您的关注。

【问题讨论】:

The man7.org has a different description 不,看这个位置的描述是一样的:MMAP Layout -> PERF_RECORD_SAMPLE -> id 我想你没看对地方。 看来,上面似乎提供了不同的文字来描述PERF_SAMPLE_IDPERF_SAMPLE_STREAM_ID的含义 嗯.. 如果我理解,你告诉我一个给我一个任意唯一的 ID,这对于发泄组是相同的,另一个只给我事件负责人的 ID?我说的对吗? 【参考方案1】:

PERF_SAMPLE_STREAM_ID 存在的主要原因是为了维护继承计数器的事件 ID。而PERF_SAMPLE_ID 将包含父计数器的事件 ID。 (如果有任何父子关系)。

继承的计数器是分配给子任务的计数器,它们源自正在分析的父任务(除非标志 --no-inherit 被传递给 perf 命令)。

这个细节在这个旧的commit中有描述。

看最新源码here,

if (sample_type & (PERF_SAMPLE_ID | PERF_SAMPLE_IDENTIFIER))
        data->id = primary_event_id(event);

    if (sample_type & PERF_SAMPLE_STREAM_ID)
        data->stream_id = event->id;

....

/*
 * If we inherit events we want to return the parent event id
 * to userspace.
 */
static u64 primary_event_id(struct perf_event *event)

    u64 id = event->id;

    if (event->parent)
        id = event->parent->id;

    return id;

上面的sn-p代码清楚地区分了结构的两个成员。这与事件是否为组长无关。

另外,需要注意的是,组中的所有事件也将计算/使用这个primary_event_id 函数。这可以看到here。因此,组中的所有事件都将包含组长的 id。

【讨论】:

很抱歉,我不懂sn-p。什么是“perf_event”结构?它的“父”成员是什么? 我也不明白你对PERF_SAMPLE_STREAM_IDPERF_SAMPLE_ID 的解释。如果你有时间,我想一个例子会更清楚。

以上是关于“perf_event_open”系统调用通过选项“PERF_RECORD_SAMPLE”返回的结构中的“id”和“stream_id”有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

Linux内核 eBPF基础:perf基础perf_event_open系统调用内核源码分析

如何从 perf_event_open 中的环形缓冲区中检索调用链以获取 PERF_RECORD_SWITCH?

perf_event_open:包括在采样时执行子进程

Linux内核 eBPF基础:perfperf_event_open系统调用与用户手册详解

深入理解系统调用

深入理解系统调用