• 关于perf_event_open怎么监控多事件的思考


    之前在用c语言构造轻量级perf工具的时候,总是监控单个type.

      29 enum perf_type_id {                                                                   
      30         PERF_TYPE_HARDWARE                      = 0,                                          
      31         PERF_TYPE_SOFTWARE                      = 1,                                       
      32         PERF_TYPE_TRACEPOINT                    = 2,                                       
      33         PERF_TYPE_HW_CACHE                      = 3,                                          
      34         PERF_TYPE_RAW                           = 4,                                         
      35         PERF_TYPE_BREAKPOINT                    = 5,                                        
      36                                                                                            
      37         PERF_TYPE_MAX,                          /* non-ABI */                              
      38 }; 

    在配置perf_event_attr时候,指定type时,只能配置一个tpye, 例如如下代码:

     58     struct perf_event_attr sw_event;
     75     memset(&sw_event,0,sizeof(struct perf_event_attr));
     76     sw_event.size=sizeof(struct perf_event_attr);
     77     sw_event.type = PERF_TYPE_SOFTWARE;  //监控软件
     79     sw_event.sample_type=PERF_SAMPLE_IP|PERF_SAMPLE_CALLCHAIN;
     80     sw_event.config=PERF_COUNT_SW_CPU_CLOCK;  //监控软件cpu时钟产生的时间。
     81     sw_event.config= 0;
     82     sw_event.sample_id_all = 1;
     83     sw_event.mmap = 1;
     84     sw_event.comm = 1;

    但是如果此时我想监控PERF_TYPE_HARDWARE该怎么办?

    首先按照上面的例子,配置一个新的perf_event_attr

     58     struct perf_event_attr hard_event;
     70     memset(&hard_event, 0, sizeof(struct perf_event_attr));
     72
     73     hard_event.type = PERF_TYPE_HARDWARE;
     74     hard_event.size = sizeof(struct perf_event_attr);
     75     hard_event.disabled = 1;
     76     hard_event.config = PERF_COUNT_HW_CPU_CYCLES; // 同样监控cpu cycles事件,但是此时是硬件方式监控
     77     hard_event.exclude_kernel = 1;             
     78     hard_event.exclude_hv = 1;                   

    其次,我们怎么才能获取到该两个perf_event_attr采集的数据呢?

    我们知道,perf的数据采集和用户态之间传输是通过句柄联系在一起的,而数据的获取可以通过read或者mmap的方式。但是怎么同时获取呢,

    下面我们需要做的就是同时创建两个采样的句柄fd1和fd2。

     92     fd1 = perf_event_open(&hard_event, pid, -1, -1, 0);
     93     if (!is_fd_vaild(fd1))
     94     {
     95         fprintf(stderr, "Error opening leader %llx
    ", hw_event.config);
     96         exit(EXIT_FAILURE);
     97     }
     98     ioctl(fd1, PERF_EVENT_IOC_ID, &id1);
     99
    100     fd2 = perf_event_open(&sf_event, pid, -1, fd1, 0); 
    101     if (!is_fd_vaild(fd2))
    102     {
    103         fprintf(stderr, "Error opening leader member %llx
    ", _event.config);
    104         exit(EXIT_FAILURE);
    105     }
    106     ioctl(fd2, PERF_EVENT_IOC_ID, &id2);

    其中后续采集的数据如果需要区分是哪个句柄采集获取的,可以通过id1和id2表示区别开来,到此处,感觉可以了,但是其实还原因不够,笔者在调试的时候

    认为这样就没有问题了,后面才发现,自己打错特错。

    因为是多tpye采样,此时的采样并不是单个,而是以group的形式进行,所以必须在设置read_format的时候,指定格式为group的形式。

    hardw_event.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;
    sw_event.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;

    此处的设置,是采到数据的关键,后面句柄的启动,只需要ENABLE其中一个即可。

    108     ioctl(fd1, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP);
    109     ioctl(fd1, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP);
    110     do_someting();
    111     ioctl(fd1, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP);

    后面的数据就不写出来了,已经很简单了。

    是时候好好总结下自己走过的路。
  • 相关阅读:
    SQL SERVER NVARCHAR字段INSERT 中文乱码问题解决
    解析$(this).data('type');
    使用HttpWebRequest发送自定义POST请求
    C#使用WebClient下载文件到本地目录
    linux开发时,想用的链接暂存
    程序进行重定位的技术按重定位的时机分类
    文件分类
    快表、页表
    操作系统的发展与分类
    网络操作系统和分布式操作系统的区别
  • 原文地址:https://www.cnblogs.com/haoxing990/p/14664266.html
Copyright © 2020-2023  润新知