【问题标题】:Perf_event_open System callperf_event_open 系统调用
【发布时间】:2018-04-14 23:41:18
【问题描述】:

我正在尝试访问 PMU 硬件性能计数器详细信息,主要关注 CPU 周期。下面是它的 C 代码。

    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/syscall.h>
    #include <string.h>
    #include <sys/ioctl.h>
    #include <linux/perf_event.h>
    #include <linux/hw_breakpoint.h>
    #include <asm/unistd.h>
    #include <errno.h>
    #include <stdint.h>
    #include <inttypes.h>
    #include <time.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)
    {
    int s = 1; 
    struct perf_event_attr pe1,pe2;
    long long count1,count2;
    int fd1,fd2;
    struct timespec time, time2;

    time.tv_sec = 0;
    time.tv_nsec = 100000000000;

    long pid = strtol(argv[1],NULL,10);
    printf("pid : %ld \n",pid);

    memset(&pe1, 0, sizeof(struct perf_event_attr));
    pe1.type = PERF_TYPE_HARDWARE;
    pe1.size = sizeof(struct perf_event_attr);
    pe1.config = PERF_COUNT_HW_INSTRUCTIONS;

    memset(&pe2, 0, sizeof(struct perf_event_attr));
    pe2.type = PERF_TYPE_HARDWARE;
    pe2.size = sizeof(struct perf_event_attr);
    pe2.config = PERF_COUNT_HW_CACHE_MISSES;

    fd1 = perf_event_open(&pe1, pid, -1, -1, 0);
    if (fd1 == -1) {
    fprintf(stderr, "Error opening leader %llx\n", pe1.config);
    exit(EXIT_FAILURE);
    }
    fd2 = perf_event_open(&pe2, pid, -1, -1, 0);
    if (fd2 == -1) {
    fprintf(stderr, "Error opening leader %llx\n", pe2.config);
    exit(EXIT_FAILURE);
    }
    while(s<=3){ 
    read(fd1, &count1, sizeof(long long));
    printf("cpu cycles : %lld \n", count1);
    read(fd2, &count2, sizeof(long long));
    printf("cache misses : %lld \n", count2);
    nanosleep(&time, &time2);
    s++;
    }

    close(fd1);
    close(fd2);
    }

当我通过将上面的代码编译为 gcc code1.c -o code1 并通过将 pid 作为参数传递为 ./code1 来运行它时,我得到以下输出

    pid : 5367 
    cpu cycles : 0 
    cache misses : 0 
    cpu cycles : 0 
    cache misses : 0 
    cpu cycles : 0 
    cache misses : 0

。这对于我系统中的大多数 pid 都是相同的情况。这是否意味着所有 pid 都没有使用任何 cpu 周期?这是否意味着该特定 PID 的周期不计算在内?

我已根据您输入的 Ioctl 命令编辑了代码,但我不确定是否必须这样做。

这里是代码

    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)   
  {
  int s = 1; 
  struct perf_event_attr pe1,pe2;
  long long count1,count2;
  int fd1,fd2;
  struct timespec time, time2;

 time.tv_sec = 2;
 time.tv_nsec = 100000000000;

 long pid = strtol(argv[1],NULL,10);
 printf("pid : %ld \n",pid);

 memset(&pe1, 0, sizeof(struct perf_event_attr));
 pe1.type = PERF_TYPE_HARDWARE;
 pe1.size = sizeof(struct perf_event_attr);
 pe1.config = PERF_COUNT_HW_CPU_CYCLES;

 memset(&pe2, 0, sizeof(struct perf_event_attr));
 pe2.type = PERF_TYPE_HARDWARE;
 pe2.size = sizeof(struct perf_event_attr);
 pe2.config = PERF_COUNT_HW_CACHE_MISSES;

 fd1 = perf_event_open(&pe1, pid, -1, -1, 0);
 if (fd1 == -1) {
    fprintf(stderr, "Error opening leader %llx\n", pe1.config);
    exit(EXIT_FAILURE);
}

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

 ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
 read(fd1, &count1, sizeof(long long));
 printf("hardware instructions : %lld \n", count1);
 fd2 = perf_event_open(&pe2, pid, -1, -1, 0);
 if (fd2 == -1) {
    fprintf(stderr, "Error opening leader %llx\n", pe2.config);
    exit(EXIT_FAILURE);
 }
 ioctl(fd2, PERF_EVENT_IOC_RESET, 0);
 ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0);

 ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
 read(fd2, &count2, sizeof(long long));
 printf("cache-misses : %lld \n", count2);

close(fd1);
close(fd2);

}

但我仍然得到 0。

    pid : 5 
    hardware instructions : 0 
    cache-misses : 0 

我理解错了吗?

此链接中的代码可以很好地提供统计信息 [链接] perf_event_open - how to monitoring multiple events

但我想通过 PID 并检查它。

【问题讨论】:

    标签: c system-calls perf


    【解决方案1】:

    您缺少启用/禁用计数器所需的ioctl 命令。像这样 -

    fd1 = perf_event_open(&pe1, pid, -1, -1, 0);
    if (fd1 == -1) {
    fprintf(stderr, "Error opening leader %llx\n", pe1.config);
    exit(EXIT_FAILURE);
    }
    
    ioctl(fd1, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0);
    
    ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
    read(fd1, &count1, sizeof(long long));
    printf("hardware instructions : %lld \n", count1);
    
    fd2 = perf_event_open(&pe2, pid, -1, -1, 0);
    if (fd2 == -1) {
    fprintf(stderr, "Error opening leader %llx\n", pe2.config);
    exit(EXIT_FAILURE);
    }
    
    ioctl(fd2, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0);
    
    ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
    read(fd2, &count2, sizeof(long long));
    printf("cache-misses : %lld \n", count2);
    

    此外,fd1 文件描述符将涉及计算退役指令的数量,而不是 CPU 周期的数量。

    编辑

    要计算硬件循环的数量,配置应该是-

    pe1.config = PERF_COUNT_HW_CPU_CYCLES

    【讨论】:

    • 那有没有办法计算周期?
    • 你好,我已经更新了代码,但我仍然得到数字为 0。任何 cmets 的原因。
    • 很遗憾,如果不查看您的代码@Susmitha,我无法确定问题所在
    • 所有 PID 都发生这种情况吗?你看过这个答案吗:-answer
    • 是的,我看了答案,但不知道在哪里给出 ioctl 语句,因此只是按照答案中发布的格式。
    猜你喜欢
    • 2014-12-25
    • 2016-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-08
    • 2014-09-22
    • 2015-06-02
    • 2012-06-30
    相关资源
    最近更新 更多