代码改变世界

Linux进程CPU的占用率计算方法

2020-10-27 16:05  宋海宾  阅读(4241)  评论(0编辑  收藏  举报

 

 

在Linux环境下计算进程的CPU占用

2.1、通过/proc/stat文件查看所有的CPU活动信息

下面实例数据是内核2.6.24-24版本以上的:

复制代码
[root@rh ~]$ cat /proc/stat
cpu  223447 240 4504182 410802165 59753 412 586209 0 0
cpu0 17625 11 193414 25755165 34590 72 16780 0 0
cpu1 12412 9 139234 25860912 1139 27 15697 0 0
cpu2 14953 0 558618 25310182 230 73 87851 0 0
cpu3 4088 0 138057 25873479 3404 19 15862 0 0
cpu4 13417 17 161123 25829756 10429 22 17155 0 0
cpu5 23935 5 331837 25605479 369 20 26095 0 0
cpu6 19320 0 319132 25619728 2060 18 30690 0 0
cpu7 18430 0 324300 25616142 4170 20 33081 0 0
cpu8 31940 0 661718 25231911 1474 15 67661 0 0
cpu9 8079 87 152035 25829339 237 19 16308 0 0
cpu10 4247 24 140052 25869331 168 18 15059 0 0
cpu11 16305 4 401473 25567904 207 14 34674 0 0
cpu12 8227 0 157815 25853353 319 10 14808 0 0
cpu13 18894 46 479709 25354279 653 26 157885 0 0
cpu14 7000 30 204760 25769743 159 16 21059 0 0
cpu15 4567 1 140899 25855452 138 16 15536 0 0
intr 1146734384 997 0 0 1 1 0 0 0 1 0 0 0 0 0 1302607 0 0 262087 0 712704 0 0 0 <...省略若干数据...>
ctxt 89793364
btime 1366591448
processes 27283
procs_running 1
procs_blocked 0
softirq 1262462448 0 63122856 50789329 1074176388 225020 0 461213 9535581 76130 64075931
复制代码

 

 

第一行的数据表示的是CPU中的使用情况。我们来解释一下这行数据各数值的含义

1)这些数值的单位都是jiffies,jiffies是内核中的一个全局变量,用来记录系统启动以来产生的节拍数,在Linux中,一个节拍大致可以理解为操作系统进程调度的最小时间片,不同的Linux内核这个值可能不同,通常在1ms到10ms之间

 

2)CPU 223447 240 4504182 410802165 59753 412 586209 0 0

  • user(223447) 从系统启动开始累积到当前时刻,处于用户态的运行时间,不包含 nice 值为负的进程。
  • nice(240) 从系统启动开始累积到当前时刻,nice 值为负的进程所占用的 CPU 时间。
  • system(4504182) 从系统启动开始累积到当前时刻,处于核心态的运行时间。
  • idle(410802165) 从系统启动开始累积到当前时刻,除 IO 等待时间以外的其他等待时间。
  • iowait(59753) 从系统启动开始累积到当前时刻,IO 等待时间。(since 2.5.41)
  • irq(412) 从系统启动开始累积到当前时刻,硬中断时间。(since 2.6.0-test4)
  • softirq(586209) 从系统启动开始累积到当前时刻,软中断时间。(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)

 

以上信息我们可以得到总的CPU活动时间为:

totalCPUTime = user + nice + system + idle + iowait + irq + softirq + stealstolen + guest

 

2.2、通过/proc/[PID]/stat 文件查看某一进程的CPU活动信息

2.2.1、存储进程新的文件目录

Linux系统贯彻"一切都是文件"的思想,所有的进程的运行状态也都可以通过读取文件来获取。/proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为内核与进程提供通信的接口。用户和应用程序可以通过/proc得到系统的信息,并且可以改变内核的某些参数。

在/proc/[PID]目录下的各个文件记录这个进程的各项运行指标。

 

2.2.2、查看进程运行的详细信息

通过查看/proc/[PID]/stat文件,可以查看进程运行的详细信息,其中包括CPU占用信息。比如

[root@rh ~]$ cat /proc/1/stat 1 (init) S 0 1 1 0 -1 4202752 3026 2635222 9 483 5 165 102346 3188016 20 0 1 0 1 19820544 384 18446744073709551615 1 1 0 0 0 0 0 4096 536962595 18446744073709551615 0 0 0 4 0 0 34 0 0

 

文件信息解释

  • pid=6873 进程(包括轻量级进程,即线程)号
  • comm=a.out 应用程序或命令的名字。
  • task_state=R 任务的状态,R:runnign, S:sleeping (TASK_INTERRUPTIBLE), D:disk sleep (TASK_UNINTERRUPTIBLE), T: stopped, T:tracing stop, Z:zombie, X:dead。
  • ppid=6723 父进程ID。
  • pgid=6873 线程组号。
  • sid=6723 该任务所在的会话组 ID。
  • tty_nr=34819(pts/3) 该任务的 tty 终端的设备号,INT(34817/256)= 主设备号,(34817-主设备号)= 次设备号。
  • tty_pgrp=6873 终端的进程组号,当前运行在该任务所在终端的前台任务(包括 shell 应用程序)的 PID。
  • task->flags=8388608 进程标志位,查看该任务的特性。
  • min_flt=77 该任务不需要从硬盘拷数据而发生的缺页(次缺页)的次数。
  • cmin_flt=0 累计的该任务的所有的 waited-for 进程曾经发生的次缺页的次数目。
  • maj_flt=0 该任务需要从硬盘拷数据而发生的缺页(主缺页)的次数。
  • cmaj_flt=0 累计的该任务的所有的 waited-for 进程曾经发生的主缺页的次数目。
  • utime=1587 该任务在用户态运行的时间,单位为 jiffies。
  • stime=1 该任务在核心态运行的时间,单位为 jiffies。
  • cutime=0 累计的该任务的所有的 waited-for 进程曾经在用户态运行的时间,单位为 jiffies。
  • cstime=0 累计的该任务的所有的 waited-for 进程曾经在核心态运行的时间,单位为 jiffies。
  • priority=25 任务的动态优先级。
  • nice=0 任务的静态优先级。
  • num_threads=3 该任务所在的线程组里线程的个数。
  • it_real_value=0 由于计时间隔导致的下一个 SIGALRM 发送进程的时延,以 jiffy 为单位。
  • start_time=5882654 该任务启动的时间,单位为 jiffies。
  • vsize=1409024(page) 该任务的虚拟地址空间大小。
  • rss=56(page) 该任务当前驻留物理地址空间的大小;Number of pages the process has in real memory,minu 3 for administrative purpose. 这些页可能用于代码,数据和栈。
  • rlim=4294967295(bytes) 该任务能驻留物理地址空间的最大值。
  • start_code=134512640 该任务在虚拟地址空间的代码段的起始地址。
  • end_code=134513720 该任务在虚拟地址空间的代码段的结束地址。
  • start_stack=3215579040 该任务在虚拟地址空间的栈的结束地址。
  • kstkesp=0 esp(32 位堆栈指针) 的当前值, 与在进程的内核堆栈页得到的一致。
  • kstkeip=2097798 指向将要执行的指令的指针, EIP(32 位指令指针)的当前值。
  • pendingsig=0 待处理信号的位图,记录发送给进程的普通信号。
  • block_sig=0 阻塞信号的位图。
  • sigign=0 忽略的信号的位图。
  • sigcatch=082985 被俘获的信号的位图。
  • wchan=0 如果该进程是睡眠状态,该值给出调度的调用点。
  • nswap 被 swapped 的页数,当前没用。
  • cnswap 所有子进程被 swapped 的页数的和,当前没用。
  • exit_signal=17 该进程结束时,向父进程所发送的信号。
  • task_cpu(task)=0 运行在哪个 CPU 上。
  • task_rt_priority=0 实时进程的相对优先级别。
  • task_policy=0 进程的调度策略,0=非实时进程,1=FIFO实时进程;2=RR实时进程

 

2.2.3、关于进程占用CPU的相关信息

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

该进程的CPU占用时间(该值包括其所有线程的CPU时间)

processCPUTime = utime + stime + cutime + cstime

 

计算某一个进程的CPU使用率processCPUUse

1)采样两个足够短的时间间隔的 CPU 快照和对应的进程快照,即读取 /proc/stat 文件,获取两个时间点的下列数据:

  • CPUT1 (user1, nice1, system1, idle1, iowait1, irq1, softirq1, stealstolen1, guest1);
  • CPUT2 (user2, nice2, system2, idle2, iowait2, irq2, softirq2, stealstolen2, guest2);

读取 /proc/[PID]/stat 文件,获取两个时间点的下列数据:

  • ProcessT1 (utime1, stime1, cutime1, cstime1);
  • ProcessT2 (utime2, stime2, cutime2, cstime2);

 

2)计算总的 CPU 时间 totalCPUTime 和进程时间 processTime:

  • CPUTime1 = user1 + nice1 + system1 + idle1 + iowait1 + irq1 + softirq1 + stealstolen1 + guest1;
  • CPUTime2 = user2 + nice2 + system2 + idle2 + iowait2 + irq2 + softirq2 + stealstolen2 + guest2;

totalCPUTime = CPUTime2 – CPUTime1;

  • processTime1 = utime1 + stime1 + cutime1 + cstime1;
  • processTime2 = utime2 + stime2 + cutime1 + cstime2;

processTime = processTime2 – processTime1;

 

3)计算该进程的 CPU 使用率 processCPUUse:

processCPUUse = processTime / totalCPUTime;