[Linux C++] 分析线程的CPU占用率模块

分析线程的CPU占用率模块

/proc/stat/

Linux内核提供了一个虚拟 /proc文件系统,为各种内部数据结构提供了接口。
/proc/stat表示CPU在各种状态下花费的时间的信息。根据这些信息,我们可以一些简单的算数得到当前CPU占用率,即在空闲状态以外的任何状态下所花费的时间百分比。
RK3308 示例

/tmp # cat /usr/local/cpu_type 
3=Rockchip RK3308
/tmp # cat /proc/stat 
cpu  471 0 1306 110314 167 0 7 0 0 0
cpu0 104 0 307 27602 43 0 7 0 0 0
cpu1 122 0 309 27612 19 0 0 0 0 0
cpu2 91 0 295 27658 15 0 0 0 0 0
cpu3 152 0 393 27440 89 0 0 0 0 0
intr 147583 0 0 108456 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 610 0 0 26271 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 170858
btime 0
processes 1810
procs_running 1
procs_blocked 0
softirq 111971 3 48131 0 384 0 0 15531 12571 0 35351

步骤

1. 通过sysconf(_SC_NPROCESSORS_ONLN) 接口获取CPU数量

2. 解析 /proc/stat文件获取CPU总的运行时间

sscanf(buf,
           "cpu  %16lu %16lu %16lu %16lu %16lu %16lu %16lu %16lu %16lu %16lu",
           &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal, &guest, &guestnice);
// sum everything up (except guest and guestnice since they are already included
// in user and nice, see http://unix.stackexchange.com/q/178045/20626) 
return user + nice + system + idle + iowait + irq + softirq + steal;

3. 获取进程下所有线程CPU运行时间

  1. 使用getpid() 接口获取当前进程PID
  2. /proc/${PID}/task是当前进程内所有线程信息的目录
  3. 通过解析 /proc/${PID}/task/$/stat获取当前线程的CPU运行时间
    utime值是进程在用户模式下运行的时间。stime值是进程在内核模式下运行的时间。
sscanf(pos,
           "%*c "                       // state
           "%*d %*d %*d %*d %*d "       // ppid, pgrp, session, tty_nr, tpgid
           "%*u"                        // flags (was %lu before Linux 2.6)
           "%*u %*u %*u %*u "           // minflt, cminflt, majflt, cmajflt
           "%lu %lu %*d %*d "           // utime, stime, cutime, cstime
           "%*d %*d %*d %*d "           // priority, nice, num_threads, itrealvalue
           "%*u "                       // starttime
           "%*u "                       // vsize
           "%ld",                       // rss
           &proc.utime, &proc.stime, &proc.vmrss);

    // convert from pages to kB
    proc.vmrss = (proc.vmrss * getpagesize()) / 1024;

4. sleep一段时间,stat文件会持续更新

// sleep some time
// note: we don't care about interrupted nanosleep calls since the
// sleeping time isn't included in any of the calculations done later
nanosleep(&sample_time, nullptr);

5. 再次获取进程下所有线程CPU运行时间,同步骤3

6. 步骤3和5的差值就是每个线程在sleep那段时间内的cpu占用时间

ProcInfo proc;
proc.tid          = proc1.tid;
proc.vmrss        = proc1.vmrss;
proc.cmd          = proc1.cmd;
uint64_t cpu_time = ((iter->utime + iter->stime) - (proc1.utime + proc1.stime));
proc.pcpu         = ((float) cpu_time / (float) elapsed_cpu_time) * 100.f * (float) num_cpus;
posted @ 2023-01-30 10:16  空水  阅读(1021)  评论(0编辑  收藏  举报