在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;