[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运行时间
- 使用getpid() 接口获取当前进程PID
- /proc/${PID}/task是当前进程内所有线程信息的目录
- 通过解析 /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;