我可以配置perf
以便在PMC溢出时收到用户空间中断或其他通知吗?
也就是说,通常当PMC溢出时,内核会处理更新计数器,获取样本或其他需要完成的簿记工作,但是我很感兴趣在用户空间中接收这些信息并采取一些措施。
根据man 2 perf_event_open的“溢出处理”部分,有perf_event_attr.watermark=0; perf_event_attr.wakeup_events=1
模式,它可能会为添加到perf_events缓冲区的每个样本在fd或调用信号处理程序上生成事件(在类似于perf record
的采样模式下)] >
watermark If set ... Otherwise, overflow notifications happen after wakeup_events samples. wakeup_events This union sets how many samples (wakeup_events) happen before an overflow notification happens. wakeup_events counts only PERF_RECORD_SAMPLE record types. To receive overflow notification for all PERF_RECORD types choose watermark and set wakeup_watermark to 1. Overflow handling Events can be set to notify when a threshold is crossed, indicating an overflow. Overflow conditions can be captured by monitoring the event file descriptor with poll(2), select(2), or epoll(7). Alterna‐ tively, the overflow events can be captured via sa signal handler, by enabling I/O signaling on the file descriptor; see the discussion of the F_SETOWN and F_SETSIG operations in fcntl(2). Overflows are generated only by sampling events (sample_period must have a nonzero value). There are two ways to generate overflow notifications. The first is to set a wakeup_events or wakeup_watermark value that will trigger if a certain number of samples or bytes have been writ‐ ten to the mmap ring buffer. In this case, POLL_IN is indicated. The other way is by use of the PERF_EVENT_IOC_REFRESH ioctl. This ioctl adds to a counter that decrements each time the event over‐ flows. When nonzero, POLL_IN is indicated, but once the counter reaches 0 POLL_HUP is indicated and the underlying event is disabled.
[有类似但不确切的方法来限制环形缓冲区的大小,例如,使用perf record的
-m 1
选项(将为每100个样本填充信号的环发出工具信号,并在fd上进行轮询)。这对于查看实际的perf_event_open参数也很有用。
$ strace -tttT -v perf record -m 1 -e cycles:u -F 20000 python -c 'print(1)' 2>&1 |less
也检查示例https://mirrors.edge.kernel.org/pub/linux/kernel/tools/perf/-任何最近的性能tar.gz,然后是tests / bp_signal.c或tests / bp_signal_overflow.c:
// SPDX-License-Identifier: GPL-2.0
...
pe.sample_period = THRESHOLD;
pe.sample_type = PERF_SAMPLE_IP;
pe.wakeup_events = 1;
...
ioctl(fd, PERF_EVENT_IOC_RESET, 0);
ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
for (i = 0; i < EXECUTIONS; i++)
test_function();
ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);