Linux下计算CPU使用率和进程CPU占用

1.Linux下CPU使用率计算

1.1 获取CPU相关数据

CPU相关的数据都存储在/proc/stat文件下

cat /proc/stat

可以获取的数据如下所示

cpu  6001763 384590 1904835 211700174 157342 0 63444 0 0 0
cpu0 521999 27988 157444 17621608 11005 0 3532 0 0 0
cpu1 513452 31008 159755 17616935 10683 0 5240 0 0 0
cpu2 530440 34565 159890 17616829 10429 0 4742 0 0 0
cpu3 519640 29076 169149 17621506 9726 0 7541 0 0 0
cpu4 514370 34605 161789 17631065 12992 0 4708 0 0 0
cpu5 523942 36103 166402 17622435 12309 0 2815 0 0 0
cpu6 468207 28426 153570 17660385 15094 0 12511 0 0 0
cpu7 494163 44118 153420 17639615 17222 0 3442 0 0 0
cpu8 468937 29524 151972 17679989 15310 0 3860 0 0 0
cpu9 486031 26383 151794 17674017 15065 0 2664 0 0 0
cpu10 479509 30625 155559 17673558 12349 0 2450 0 0 0
cpu11 481070 32163 164086 17642227 15152 0 9936 0 0 0
......

对于CPU使用率的计算,我们需要关注第一行,即

cpu  6001763 384590 1904835 211700174 157342 0 63444 0 0 0

上述一行中的每个数值单位都是jiffies[1]

分析上述文本,从左到右的文本依次表示

  • user(6001763) 从系统启动开始累积到当前时刻,处于用户态的运行时间,不包含 nice 值为负的进程。
  • nice(384590) 从系统启动开始累积到当前时刻,nice 值为负的进程所占用的 CPU 时间。
  • system(1904835) 从系统启动开始累积到当前时刻,处于核心态的运行时间。
  • idle(211700174) 从系统启动开始累积到当前时刻,除 IO 等待时间以外的其他等待时间。
  • iowait(157342) 从系统启动开始累积到当前时刻,IO 等待时间。(since 2.5.41)
  • irq(0) 从系统启动开始累积到当前时刻,硬中断时间。(since 2.6.0-test4)
  • softirq(63444) 从系统启动开始累积到当前时刻,软中断时间。(since 2.6.0-test4)
  • stealstolen(0) Which is the time spent in other operating systems when running in a virtualized environment.(since 2.6.11)
  • guest(0) Which is the time spent running a virtual CPU for guest operating systems under the control of the Linux kernel.(since 2.6.24)
  • guestnice(0)

通过以上数值,可以获得系统启动开始,CPU总的活动时间[2]totalCPUTime为:

\[totalCPUTime(jiffies)=user+nice+system+idle+iowait+irq+softirq+stealstolen+guest+guestnice \]

CPU总的空闲时间idleCPUTime为:

\[idleCPUTime(jiffies)=idle \]

在C++中,可以通过以下代码计算得到jiffies的值:

#include <unistd.h>  
uint16_t cpu_hz = sysconf(_SC_CLK_TCK);
uint16_t jiffies = 1000 / cpu_hz;

1.2 任意时间间隔计算CPU使用率

  • 假设读取两次/proc/stat文件,可以获取两个不同的totalCPUTime,记为totalCPUTime0和totalCPUTime1
  • 同样的,可以得到idleCPUTime0和idleCPUTime1
  • 记deltaTotalCPUtime为totalCPUTime1和totalCPUTime0的差值
  • 记deltaIdleCPUTime为idleCPUTime1和idleCPUTime0的差值

那么,可以计算得到这两次读取之间CPU的使用率[3]

\[CPU\%= {deltaTotalCPUtime-deltaIdleCPUTime \over deltaTotalCPUtime} \times 100\% \]

2.Linux下进程的CPU使用率计算

2.1 获取进程的CPU相关数据

不同pid的进程相关的数据,都存储在/proc/${pid}/stat文件下

cat /proc/${pid}/stat

以pid为5995的进程为例

cat /proc/5995/stat

获取的数据如下所示

5995 (gnome-terminal-) S 4128 5995 5995 0 -1 4194304 26845 4629217 403 404 
79290 9349 12450 16636 20 0 5 0 12069 950829056 21731 
......

其中,前13项参数与进程CPU使用率计算无关,无需关注

  • utime=79290 该任务在用户态运行的时间,单位为jiffies
  • stime=9349 该任务在核心态运行的时间,单位为jiffies
  • cutime=12450 累计的该任务的所有的waited-for进程曾经在用户态运行的时间,单位为jiffies
  • cstime=16636 累计的该任务的所有的waited-for进程曾经在核心态运行的时间,单位为jiffies

2.2 任意时间间隔计算进程的CPU使用率

通过计算可以得到进程CPU累计运行时间为:

\[totalProcCPUTime(jiffies)=utime+stime+cutime+cstime \]

通过两次读取/proc/${pid}/stat文件,可以得到两次间隔之间,进程CPU累计的运行时间:

\[deltaTotalProcCPUTime(jiffies)=totalProcCPUTime1-totalProcCPUTime0 \]

根据1.1中计算deltaTotalCPUtime的方式,获取deltaTotalCPUtime的值

假设CPU核心数为n,那么可以得到进程的CPU使用率为:

\[procCPU\%= {deltaTotalProcCPUTime \over deltaTotalCPUtime }\cdot n \times 100\% \]

2.3 固定时间间隔计算进程的CPU使用率

假设应用程序以clock的时间间隔循环执行,通过两次运行可以得到进程CPU的差值为deltaTotalProcCPUtime

那么可以得到进程的CPU使用率为:

\[procCPU \% ={deltaTotalProcCPUTime \over clock} \cdot jiffies \times 100 \% \]



  1. jiffies是内核中的一个全局变量,用来记录系统启动以来产生的节拍数,在Linux中,一个节拍大致可以理解为操作系统进程调度的最小时间片,不同的Linux内核这个值可能不同 ↩︎

  2. CPU总的活动时间在多核CPU中为所有CPU核心的活动时间;假设CPU_HZ为100Hz,即1秒有100个jiffies,那么jiffies为10ms;在1s内,12核CPU理论上应该有100*12个jiffies,16核CPU理论上应该有100*16个jiffies ↩︎

  3. 这样计算得到的CPU使用率最大为100%,与CPU核心数无关 ↩︎

posted @ 2023-05-24 15:39  umichan  阅读(1738)  评论(0编辑  收藏  举报