【问题标题】:perf_event_open can not open more than 7 fdperf_event_open 不能打开超过 7 个 fd
【发布时间】:2017-12-15 09:58:20
【问题描述】:

这是我的代码,perf_event_open 不能打开超过 7 个 fds

#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/perf_event.h>
#include <asm/unistd.h>

static long
perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
                int cpu, int group_fd, unsigned long flags)
{
    int ret;

    ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
                   group_fd, flags);
    return ret;
}

int
main(int argc, char **argv)
{
    struct perf_event_attr pe;
    long long count;
    int fd,fd1,fd2,fd3,fd4,fd5,fd6,fd7,fd8;

    memset(&pe, 0, sizeof(struct perf_event_attr));
    pe.type = PERF_TYPE_HARDWARE;
    pe.size = sizeof(struct perf_event_attr);
    pe.config = PERF_COUNT_HW_INSTRUCTIONS;
    pe.disabled = 1;
    pe.exclude_kernel = 1;
    pe.exclude_hv = 1;

    fd = perf_event_open(&pe, 0, -1, -1, 0);
    if (fd == -1) {
       fprintf(stderr, "Error opening leader %llx, errno:%d, reason:%s\n", pe.config, errno, strerror(errno));
       exit(EXIT_FAILURE);
    }

    ioctl(fd, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);

    printf("Measuring instruction count for this printf\n");

    ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
    read(fd, &count, sizeof(long long));

    printf("Used %lld instructions\n", count);

    // ----------------------------------------------------------------------
    memset(&pe, 0, sizeof(struct perf_event_attr));
    pe.type = PERF_TYPE_HARDWARE;
    pe.size = sizeof(struct perf_event_attr);
    pe.config = PERF_COUNT_HW_CPU_CYCLES;
    pe.disabled = 1;
    pe.exclude_kernel = 1;
    pe.exclude_hv = 1;

    fd1 = perf_event_open(&pe, 0, -1, -1, 0);
    if (fd1 == -1) {
       fprintf(stderr, "Error opening leader %llx, errno:%d, reason:%s\n", pe.config, errno, strerror(errno));
       exit(EXIT_FAILURE);
    }

    ioctl(fd1, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0);

    printf("Measuring cpu cycles count for this printf\n");

    ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
    read(fd1, &count, sizeof(long long));

    printf("Used %lld instructions\n", count);
    // ----------------------------------------------------------------------

    // ----------------------------------------------------------------------
    memset(&pe, 0, sizeof(struct perf_event_attr));
    pe.type = PERF_TYPE_HARDWARE;
    pe.size = sizeof(struct perf_event_attr);
    pe.config = PERF_COUNT_HW_CACHE_REFERENCES;
    pe.disabled = 1;
    pe.exclude_kernel = 1;
    pe.exclude_hv = 1;

    fd2 = perf_event_open(&pe, 0, -1, -1, 0);
    if (fd2 == -1) {
       fprintf(stderr, "Error opening leader %llx, errno:%d, reason:%s\n", pe.config, errno, strerror(errno));
       exit(EXIT_FAILURE);
    }

    ioctl(fd2, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0);

    printf("Measuring cache references count for this printf\n");

    ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
    read(fd2, &count, sizeof(long long));

    printf("Used %lld instructions\n", count);
    // ----------------------------------------------------------------------

    // ----------------------------------------------------------------------
    memset(&pe, 0, sizeof(struct perf_event_attr));
    pe.type = PERF_TYPE_HARDWARE;
    pe.size = sizeof(struct perf_event_attr);
    pe.config = PERF_COUNT_HW_CACHE_MISSES;
    pe.disabled = 1;
    pe.exclude_kernel = 1;
    pe.exclude_hv = 1;

    fd3 = perf_event_open(&pe, 0, -1, -1, 0);
    if (fd3 == -1) {
       fprintf(stderr, "Error opening leader %llx, errno:%d, reason:%s\n", pe.config, errno, strerror(errno));
       exit(EXIT_FAILURE);
    }

    ioctl(fd3, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd3, PERF_EVENT_IOC_ENABLE, 0);

    printf("Measuring cache misses count for this printf\n");

    ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
    read(fd3, &count, sizeof(long long));

    printf("Used %lld instructions\n", count);
    // ----------------------------------------------------------------------

    // ----------------------------------------------------------------------
    memset(&pe, 0, sizeof(struct perf_event_attr));
    pe.type = PERF_TYPE_HARDWARE;
    pe.size = sizeof(struct perf_event_attr);
    pe.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
    pe.disabled = 1;
    pe.exclude_kernel = 1;
    pe.exclude_hv = 1;

    fd4 = perf_event_open(&pe, 0, -1, -1, 0);
    if (fd4 == -1) {
       fprintf(stderr, "Error opening leader %llx, errno:%d, reason:%s\n", pe.config, errno, strerror(errno));
       exit(EXIT_FAILURE);
    }

    ioctl(fd4, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd4, PERF_EVENT_IOC_ENABLE, 0);

    printf("Measuring branch instructions count for this printf\n");

    ioctl(fd4, PERF_EVENT_IOC_DISABLE, 0);
    read(fd4, &count, sizeof(long long));

    printf("Used %lld instructions\n", count);
    // ----------------------------------------------------------------------

    // ----------------------------------------------------------------------
    memset(&pe, 0, sizeof(struct perf_event_attr));
    pe.type = PERF_TYPE_HARDWARE;
    pe.size = sizeof(struct perf_event_attr);
    pe.config = PERF_COUNT_HW_BRANCH_MISSES;
    pe.disabled = 1;
    pe.exclude_kernel = 1;
    pe.exclude_hv = 1;

    fd5 = perf_event_open(&pe, 0, -1, -1, 0);
    if (fd5 == -1) {
       fprintf(stderr, "Error opening leader %llx, errno:%d, reason:%s\n", pe.config, errno, strerror(errno));
       exit(EXIT_FAILURE);
    }

    ioctl(fd5, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd5, PERF_EVENT_IOC_ENABLE, 0);

    printf("Measuring branch misses count for this printf\n");

    ioctl(fd5, PERF_EVENT_IOC_DISABLE, 0);
    read(fd5, &count, sizeof(long long));

    printf("Used %lld instructions\n", count);
    // ----------------------------------------------------------------------

    // ----------------------------------------------------------------------
    memset(&pe, 0, sizeof(struct perf_event_attr));
    pe.type = PERF_TYPE_HARDWARE;
    pe.size = sizeof(struct perf_event_attr);
    pe.config = PERF_COUNT_HW_BUS_CYCLES;
    pe.disabled = 1;
    pe.exclude_kernel = 1;
    pe.exclude_hv = 1;

    fd6 = perf_event_open(&pe, 0, -1, -1, 0);
    if (fd6 == -1) {
       fprintf(stderr, "Error opening leader %llx, errno:%d, reason:%s\n", pe.config, errno, strerror(errno));
       exit(EXIT_FAILURE);
    }

    ioctl(fd6, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd6, PERF_EVENT_IOC_ENABLE, 0);

    printf("Measuring bus cycles count for this printf\n");

    ioctl(fd6, PERF_EVENT_IOC_DISABLE, 0);
    read(fd6, &count, sizeof(long long));

    printf("Used %lld instructions\n", count);
    // ----------------------------------------------------------------------

    // ----------------------------------------------------------------------
    memset(&pe, 0, sizeof(struct perf_event_attr));
    pe.type = PERF_TYPE_HARDWARE;
    pe.size = sizeof(struct perf_event_attr);
    pe.config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND;
    pe.disabled = 1;
    pe.exclude_kernel = 1;
    pe.exclude_hv = 1;

    fd7 = perf_event_open(&pe, 0, -1, -1, 0);
    if (fd7 == -1) {
       fprintf(stderr, "Error opening leader %llx, errno:%d, reason:%s\n", pe.config, errno, strerror(errno));
       exit(EXIT_FAILURE);
    }

    ioctl(fd7, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd7, PERF_EVENT_IOC_ENABLE, 0);

    printf("Measuring stalled cycles frontend count for this printf\n");

    ioctl(fd7, PERF_EVENT_IOC_DISABLE, 0);
    read(fd7, &count, sizeof(long long));

    printf("Used %lld instructions\n", count);
    // ----------------------------------------------------------------------

    // ----------------------------------------------------------------------
    memset(&pe, 0, sizeof(struct perf_event_attr));
    pe.type = PERF_TYPE_HARDWARE;
    pe.size = sizeof(struct perf_event_attr);
    pe.config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND;
    pe.disabled = 1;
    pe.exclude_kernel = 1;
    pe.exclude_hv = 1;

    fd8 = perf_event_open(&pe, 0, -1, -1, 0);
    if (fd8 == -1) {
       fprintf(stderr, "Error opening leader %llx, errno:%d, reason:%s\n", pe.config, errno, strerror(errno));
       exit(EXIT_FAILURE);
    }

    ioctl(fd8, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd8, PERF_EVENT_IOC_ENABLE, 0);

    printf("Measuring stalled cycles backend count for this printf\n");

    ioctl(fd8, PERF_EVENT_IOC_DISABLE, 0);
    read(fd8, &count, sizeof(long long));

    printf("Used %lld instructions\n", count);
    // ----------------------------------------------------------------------

    close(fd);
    close(fd1);
    close(fd2);
    close(fd3);
    close(fd4);
    close(fd5);
    close(fd6);
    close(fd7);
    close(fd8);
}

这里是输出,只打开了前 7 个 perf 事件,其余的将失败并显示 errno 2。

Measuring instruction count for this printf 
Used 3857 instructions 
Measuring cpu cycles count for this printf 
Used 1546 instructions
Measuring cache references count for this printf
Used 17 instructions
Measuring cache misses count for this printf
Used 0 instructions
Measuring branch instructions count for this printf
Used 194 instructions
Measuring branch misses count for this printf
Used 12 instructions
Measuring bus cycles count for this printf
Used 34 instructions
Error opening leader 7, errno:2, reason:No such file or directory

我在 linux 手册页中没有找到有关此限制的任何说明,请有人告诉我发生了什么,非常感谢。 我的操作系统版本是centos 6.5。

【问题讨论】:

    标签: c linux perf


    【解决方案1】:

    这与打开性能事件的数量无关,您只需删除前 7 个 perf_event_open 调用即可轻松找到。

    没有这样的文件或目录 (ENOENT) 与打开的文件太多 (EMFILE) 不同。 perf_event_open 的 manpage 解释了返回码:

    ENOENT 如果类型设置无效则返回。此错误也会针对某些不受支持的通用事件返回

    该事件在您的系统上根本不可用(使用给定的内核)。 This answer 讨论了现代 CPU 上 PERF_COUNT_HW_STALLED_CYCLES_*END 事件的可用性。

    【讨论】:

    • @Jim 很高兴为您提供帮助,如果帖子回答了您的问题,请单击左侧的复选标记将其标记为已接受。
    猜你喜欢
    • 2012-03-25
    • 2023-03-19
    • 2013-06-16
    • 2017-09-10
    • 2018-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-15
    相关资源
    最近更新 更多