perf_event_open无法打开超过7 fd

时间:2017-12-15 09:58:20

标签: c linux perf

这是我的代码,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手册页中没有找到关于这个限制的任何说明,有些人会告诉我发生了什么,非常感谢。 我的os版本是centos 6.5。

1 个答案:

答案 0 :(得分:2)

这与与开放式整体事件的数量无关,因为您只需删除前7个perf_event_open来电即可轻松找到。

没有此类文件或目录ENOENT)与太多打开文件EMFILE)不同。 perf_event_open的联机帮助页解释了返回码:

  

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

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