В чем разница между "id" и "stream_id" в структуре, возвращаемой с опцией "PERF_RECORD_SAMPLE" системным вызовом "perf_event_open"? - PullRequest
1 голос
/ 20 февраля 2020

Я пытаюсь написать кусок кода, используя системный вызов perf_event_open. Но я не понимаю реальной разницы между полями id и stream_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.

Но проблема здесь: документация кажется непоследовательной.

Имею ли я что-то пропустил?

Спасибо за внимание.

1 Ответ

0 голосов
/ 22 февраля 2020

Основная причина наличия PERF_SAMPLE_STREAM_ID заключается в том, чтобы поддерживать идентификаторы событий унаследованных счетчиков. В то время как PERF_SAMPLE_ID будет содержать идентификатор события родительских счетчиков. (если есть какие-либо отношения родитель-потомок).

Унаследованные счетчики - это те счетчики, которые выделены дочерним задачам и происходят из профилируемой родительской задачи (если только флаг --no-inherit не передается perf команда).

Эта деталь описана в этом старом коммите .

Глядя на последний исходный код здесь ,

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;
}

Приведенный выше фрагмент кода четко различает два члена структуры. Это независимо от того, является ли событие лидером группы или нет.

Также важно отметить, что все события в группе также будут вычислять / использовать эту функцию primary_event_id. Это можно увидеть здесь . Таким образом, все события в группе будут содержать идентификатор лидера группы.

...