1 #include <stdlib.h> 2 #include <stdio.h> 3 #include <unistd.h> 4 #include <string.h> 5 #include <sys/ioctl.h> 6 #include <linux/perf_event.h> 7 #include <asm/unistd.h> 8 #include <sys/mman.h> 9 #include <sys/stat.h> 10 #include <poll.h> 11 #include <signal.h> 12 #include <fcntl.h> 13 14 15 #include <map> 16 #include <unordered_set> 17 #include <queue> 18 using namespace std; 19 20 21 #define error(msg) do { perror(msg); exit(1); } while(0) 22 #define MAXN 128 23 24 static long perf_event_open(struct perf_event_attr *perf_event, pid_t pid, int cpu, int group_fd, unsigned long flags) { 25 return syscall(__NR_perf_event_open, perf_event, pid, cpu, group_fd, flags); 26 } 27 static void *addr = NULL; 28 static int fd = -1; 29 static long long psize; 30 vector<int> res; 31 static unsigned long long cx_count=0, g_stime=0, g_total=0, g_rtotal=0; 32 int alive=1; 33 void int_exit(int s) { 34 for (auto x: res) close(x); 35 res.clear(); 36 alive=0; 37 } 38 39 40 41 #define MAXCPU 1024 42 char buf[10240]; 43 int main(int argc, char *argv[]) { 44 if (argc != 2) { printf("need pid\n"); return 1; } 45 int pid = atoi(argv[1]); if (pid<=0) { printf("invalid pid %s\n", argv[1]); return 1; } 46 // find cgroup 47 char xb[256], xb2[256]; 48 int i, j, k; 49 sprintf(xb, "/proc/%d/cgroup", pid); 50 FILE* fp = fopen(xb, "r"); 51 if (fp==NULL) error("fail to open cgroup file"); 52 char *p; 53 xb2[0]=0; 54 int cgroup_name_len=0; 55 while(1) { 56 p = fgets(xb, sizeof(xb), fp); if (p==NULL) break; 57 i=0; while(p[i]&&p[i]!=':') i++; if (p[i]==0) continue; 58 if (strstr(p, "perf_event")) { 59 i++; while(p[i]!=':'&&p[i]) i++; if (p[i]!=':') continue; i++; 60 j=i; while(p[j]!='\r'&&p[j]!='\n'&&p[j]!=0) j++; p[j]=0; 61 sprintf(xb2, "/sys/fs/cgroup/perf_event%s", p+i); 62 cgroup_name_len=j-i; 63 break; 64 } else if (p[i+1]==':') { 65 i+=2; j=i; while(p[j]!='\r'&&p[j]!='\n'&&p[j]!=0) j++; p[j]=0; 66 sprintf(xb2, "/sys/fs/cgroup/%s", p+i); 67 cgroup_name_len=j-i; 68 } 69 } 70 fclose(fp); 71 if (xb2[0]==0) error("no proper cgroup found\n"); 72 if (cgroup_name_len<2) { 73 printf("cgroup %s seems to be root, not allowed\n", xb2); 74 return -1; 75 } 76 77 printf("try to use cgroup %s\n", xb2); 78 int cgroup_id = open(xb2, O_CLOEXEC); 79 if (cgroup_id<=0) { perror("error open cgroup dir"); return 1; } 80 81 // start perf event 82 psize = sysconf(_SC_PAGE_SIZE); // getpagesize(); 83 int cpu_num = sysconf(_SC_NPROCESSORS_ONLN); 84 struct perf_event_attr attr; 85 memset(&attr, 0, sizeof(attr)); 86 attr.type = PERF_TYPE_SOFTWARE; 87 attr.size = sizeof(attr); 88 attr.sample_period = 1; 89 attr.wakeup_events = 1; 90 attr.config = PERF_COUNT_SW_PAGE_FAULTS_MAJ; 91 for (i=0, k=0; i<cpu_num&&i<MAXCPU; i++) { 92 printf("attaching cpu %d\n", i); 93 fd = perf_event_open(&attr, cgroup_id, i, -1, PERF_FLAG_FD_CLOEXEC|PERF_FLAG_PID_CGROUP); 94 if (fd<0) { perror("fail to open perf event"); continue; } 95 res.push_back(fd); 96 } 97 if (res.size()==0) { printf("no cpu event attached at all\n"); return 1; } 98 99 signal(SIGINT, int_exit); 100 signal(SIGTERM, int_exit); 101 102 unsigned long long counter; 103 while(alive) { 104 sleep(1); 105 counter = 0; 106 for (auto x:res) { 107 k = read(x, buf, sizeof(buf)); 108 if (k>=8) { 109 counter += *(unsigned long long *)buf; 110 } 111 if (k<0) perror("fail to read"); 112 } 113 printf("counter --> %lld\n", counter); 114 } 115 116 117 int_exit(0); 118 return 0; 119 } 120