gpt4 book ai didi

c - perf_event_open 系统调用

转载 作者:太空宇宙 更新时间:2023-11-04 03:17:42 25 4
gpt4 key购买 nike

我正在尝试访问 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 并检查它。

最佳答案

您缺少启用/禁用计数器所需的 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

关于c - perf_event_open 系统调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49837176/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com