perf_event_open(2)
Open a file descriptor for a hardware or software performance counter.
- Since
- Linux 2.6.31check your kernel →
- glibc
- none (use syscall(2))
- System
- Linux
- Man page
- perf_event_open(2)
Synopsis
#include <linux/perf_event.h>
#include <sys/syscall.h>
#include <unistd.h>
/* no glibc wrapper; call via syscall(2) */
int perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu,
int group_fd, unsigned long flags);Rod's take
perf stat calls perf_event_open(2). Call it yourself when you need counters inline without a subprocess or perf.data file. Use group_fd to atomic-read multiple counters from the same scheduling window. Always request PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_TOTAL_TIME_RUNNING and scale accordingly when the kernel multiplexes more events than the PMU has physical registers. Set disabled=1 and gate with ioctl(PERF_EVENT_IOC_ENABLE/DISABLE) to control the measurement window precisely.
Flags and arguments that matter
| Name | What it does |
|---|---|
| PERF_TYPE_HARDWARE | CPU PMU counter; config is one of PERF_COUNT_HW_* (cycles, instructions, cache-misses, branch-misses, etc.). |
| PERF_TYPE_SOFTWARE | Kernel counter; config is one of PERF_COUNT_SW_* (cpu-clock, page-faults, context-switches, etc.). |
| PERF_TYPE_RAW | Vendor-specific PMU event code; config is the raw event selector from the CPU architecture manual. |
| PERF_FORMAT_GROUP | Read all group members atomically in one read(2) call on the leader fd. |
| PERF_FORMAT_TOTAL_TIME_ENABLED / PERF_FORMAT_TOTAL_TIME_RUNNING | Include nanoseconds the counter was enabled vs. actually running; divide to detect PMU multiplexing. |
| PERF_FLAG_FD_CLOEXECLinux 3.14 | Set O_CLOEXEC on the returned fd. |
| CAP_PERFMONLinux 5.8 | Required for system-wide (pid=-1) access; replaces CAP_SYS_ADMIN for perf in Linux 5.8. |
Errors you will actually hit
| errno | Meaning |
|---|---|
| EACCES | perf_event_paranoid is too restrictive for the requested scope without the required capability. |
| EINVAL | Invalid event type or config, or pid=-1 and cpu=-1 simultaneously. |
| EMFILE | Too many open file descriptors; each event costs one fd. |
Example
#include <linux/perf_event.h>
#include <sys/ioctl.h>
#include <sys/syscall.h>
#include <unistd.h>
struct perf_event_attr attr = {
.type = PERF_TYPE_HARDWARE,
.size = sizeof(attr),
.config = PERF_COUNT_HW_INSTRUCTIONS,
.disabled = 1,
.exclude_kernel = 1,
};
int fd = syscall(SYS_perf_event_open, &attr, 0, -1, -1, PERF_FLAG_FD_CLOEXEC);
ioctl(fd, PERF_EVENT_IOC_RESET, 0);
ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
/* ... work ... */
ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
uint64_t count;
read(fd, &count, sizeof(count));Trimmed from the full walkthrough in perf_event_open(2): hardware counters without the wrapper.
BSD equivalent
FreeBSD: hwpmc(4) and pmc(3)/pmcstat(8). Allocate via pmc_allocate(3), attach to a process, read via pmc_read(3). No group-atomic read. pmcstat -S instructions -p $pid is the closest equivalent.
The long version, from the console
Sources
Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.
