Документация https://github.com/torvalds/linux/blob/master/tools/perf/design.txt содержит описание mmaped ring, а perf script
/ perf script -D
может декодировать данные кольца, когда они сохраняются в файле perf.data. Некоторые части do c устарели, но они все еще полезны для описания системного вызова perf_event_open
.
Первая страница mmap - это страница метаданных, остальные 2 ^ n страниц заполнены событиями, где каждое событие имеет заголовок struct perf_event_header
из 8 байтов.
Как указано, асинхронные события, такие как переполнение счетчика или отслеживание mmap PROT_EXEC, регистрируются в кольцевом буфере. Этот кольцевой буфер создается и доступен через mmap ().
Размер mmap должен составлять 1 + 2 ^ n страниц, где первая страница является страницей метаданных (struct perf_event_mmap_page), которая содержит различные биты информация, например, где находится заголовок кольцевого буфера.
/*
* Structure of the page that can be mapped via mmap
*/
struct perf_event_mmap_page {
__u32 version; /* version number of this structure */
__u32 compat_version; /* lowest version this is compat with */
...
}
Следующие 2 ^ n страниц являются кольцевым буфером, который содержит события вида:
#define PERF_RECORD_MISC_KERNEL (1 << 0)
#define PERF_RECORD_MISC_USER (1 << 1)
#define PERF_RECORD_MISC_OVERFLOW (1 << 2)
struct perf_event_header {
__u32 type;
__u16 misc;
__u16 size;
};
enum perf_event_type
design.txt
do c имеет неверные значения для enum perf_event_type, проверьте фактические исходные коды подсистемы ядра perf_events - https://github.com/torvalds/linux/blob/master/include/uapi/linux/perf_event.h#L707. Этот файл uapi / linux / perf_event.h также имеет некоторые структурные подсказки в комментариях, например
* #
* # The RAW record below is opaque data wrt the ABI
* #
* # That is, the ABI doesn't make any promises wrt to
* # the stability of its content, it may vary depending
* # on event, hardware, kernel version and phase of
* # the moon.
* #
* # In other words, PERF_SAMPLE_RAW contents are not an ABI.
* #
*
* { u32 size;
* char data[size];}&& PERF_SAMPLE_RAW
*...
* { u64 size;
* char data[size];
* u64 dyn_size; } && PERF_SAMPLE_STACK_USER
*...
PERF_RECORD_SAMPLE = 9,