引言
在Linux
系統下top
命令是一個查看cpu
使用率的一個重要的命令,今天我們就來說說這個重要的命令;
1.top命令顯示解析
在Linux
終端下輸入top
就會產生動態的cpu
使用情況的圖表,現在我們來一個一個解釋上圖中顯示的是什麼東西;
top - 19:45:03 up 54 min, 1 user, load average: 0.79, 0.82, 3.17
第一個時間19:45:03
表示當前時間;
54min
表示cpu
運行了多少時間,簡單來說就是開始多久了;
1 user
表示當前有一個用戶;
關於這個load average
表示平均負載,這個我們後面詳細介紹;
Tasks: 238 total, 1 running, 237 sleeping, 0 stopped, 0 zombie
Tasks
表示任務;(這裏的任務可以理解爲進程)
238 total
表示當前總共有238
個任務;
1 running
表示現在有一個任務是在運行中的
237 sleeping
表示睡眠進程數
0 stopped
表示停止進程數,這個表示被中斷的進程,比如正在gdb
調試中的程序;
0 zombie
表示殭屍進程數量,這些在後面都會講解;
%Cpu(s): 14.6 us, 0.7 sy, 0.0 ni, 84.4 id, 0.2 wa, 0.0 hi, 0.1 si, 0.0 st
這一行表示了cpu
的使用情況;
14.6 us
表示用戶使用cpu
佔比;
0.7 sy
表示內核使用cpu
佔比;
84.4 id
表示空閒cpu
佔比;
上述三個加起來應該是1
也就是100%
在cpu
被最大限度使用時,用戶使用和內核使用加起來是100%
,此時空閒cpu
爲0
0.0 ni
表示用戶改過優先級的進程佔多少;
0.2 wa
表示待輸入輸出的cpu
佔比
0.0 hi
表示硬中斷cpu
佔比
0.0 si
表示軟中斷cpu
佔比
0.0 st
表示虛擬機佔比
MiB Mem : 7746.9 total, 5404.9 free, 1177.0 used, 1164.9 buff/cache
7746.9 total
—物理內存總量
5404.9 free
----空閒內存
1177.0 user
----正在使用的內存
1164.9 buff/cache
—作爲內核緩存的內存量
MiB Swap: 4096.0 total, 4096.0 free, 0.0 used. 5896.5 avail Mem
4096.0 total
—交換區總量
4096.0 free
—空閒交換區總量
0.0 used
—使用交換區總量
5896.5 avail Men
—可用於進程下一次分配的物理內存數量
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
PID
—進程id
USER
—進程所有者的用戶名
PR
—優先級(數字越小優先級越高)
NI
—優先級
關於NI
和PR
的區別我們將在後面講解
VIRT
—進程使用的虛擬內存總量
RES
—進程使用的未被換出的物理內存大小
SHR
—共享內存大小
S
—進程狀態(D=不可中斷的睡眠狀態 R=運行 S=睡眠 T=跟蹤/停止 Z=殭屍進程)
%CPU
—CPU佔用百分比
%MEM
—進程使用的物理內存百分比
TIME+
—進程使用的時間單位毫秒
COMMAND
—命令名
2.殭屍進程
簡單來說就是子進程已經死了但是父進程還在運行,而且父進程沒有回收子進程,此時子進程就會變成殭屍進程;
#include <unistd.h>
#include <stdio.h>
int main()
{
int pid;
pid = fork();
if (pid == 0) {
} else {
while (1) {
}
}
return 0;
}
我們現在將這個進程丟到後臺執行;
我們通過執行ps
命令就可以看到我們正在運行的進程;
我們可以看到10111
是我們運行程序的進程id而下面的10112
是該進程創建的子進程id;在這個進程後面有一個<defunct>
這個就表示這個進程現在是個殭屍進程;
接着我們看一下top
此時的情況:
我們可以看到第一行的負載增加了;
第二行zombie
變成了一個,那個就是我們創建的殭屍進程;
而且現在有兩個進程正在運行,其中一個就是我們的a.out
;
我們在圖片的最後一行可以看到關於我們這個進程的信息,因爲只有他一個程序在跑,所以這個進程佔用的cpu
很高;
那我們能不能找到那個殭屍進程呢,是可以的
我們可以看到殭屍進程是沒有內存的,而且在進程狀那裏變成了Z
,就表示該進程是一個殭屍進程;
3.ctrl+z處理進程和停止進程
現在有一個這樣的程序
#include <stdio.h>
int main()
{
while (1) {
}
return 0;
}
我們來執行一下他然後ctrl+z
掉這個進程;
現在我們在top
中觀察一下
我們可以發現多了一個停止的進程;我們在下面來找一下這個進程;
這個進程是T
表示一個停止的進程;
我們現在獲得了這個進程的ID那我們嘗試kill
掉這個進程
我們發現還是有一個停止中的進程;
我發現這個進程並沒有被kill
掉;
於是我們使用一個暴力的手段kill -9 (進程號)
;
這下這個ctrl+z
的進程終於被kill
掉了;
3.1kill 和 kill -9
kill
命令的格式是
kill -Signal pid
默認情況下是15
;
默認參數下,kill
發送SIGTERM(15)
信號給進程,告訴進程,你需要被關閉,請自行停止運行並退出;
剛纔我們在kill
被ctrl+z
的進程時失敗,可能是因爲他已經是一個停止的進程了;
相比kill -15
,kill -9
就暴力很多了;
kill -9
發送SIGKILL
信號給進程,告訴進程,你被終結了,請立刻退出;
TERM(或數字9)
表示“無條件終止”;
因此kill - 9
表示強制殺死該進程,與SIGTERM
相比,這個信號不能被捕獲或忽略,同時接收這個信號的進程在收到這個信號時不能執行任何清理;
3.2其他的停止程序的方法
我們在這裏演示一個最常見的gdb
;
然後我們重開一個終端,執行top
命令;
我們可以看到出來了一個停止的進程;
我們在下面來找一下這個進程;
我們可以看到被gdb
中斷的進程的狀態是t
;
同樣的這個進程不能被普通kill
掉;
我們會發現,他被kill
以後變成了一個殭屍進程;
在另一個終端下執行的gdb
,我們執行一下n
命令
我們會發現這個已經運行不了了;那現在我們讓這個程序重新運行一下;
然後我們來看一下這邊的top
我們發現他重新變成了一個停止的進程;
4.孤兒進程
什麼是孤兒進程?
我們這裏和殭屍進程做一個區別;
殭屍進程是父進程一直運行,子進程死掉後父進程沒有回收,子進程就會變成殭屍進程;
孤兒進程就是子進程一直在運行,但是父進程已經死了;然後他被init
這個進程收養;
我們先來看一個正常的進程;(父子進程都在運行的)
#include <unistd.h>
#include <stdio.h>
int main()
{
int pid;
pid = fork();
if (pid == 0) {
while (1) {
}
} else {
while (1) {
}
}
return 0;
我們運行一下這個程序,然後用pstree
這個命令來看一下;
我們可以在這個圖片的最下面看到在一個終端下運行着我們的a.out
這個程序創建了一個進程,我們就可以看到這樣的關係;
那現在如果父進程死掉,會怎麼樣;
#include <unistd.h>
#include <stdio.h>
int main()
{
int pid;
pid = fork();
if (pid == 0) {
while (1) {
}
} else {
}
return 0;
}
我們可以看到這個子進程被systemd
這個進程收養了;
此時這個子進程我們叫做孤兒進程;
我們上面說到孤兒進程是被init
這個進程收養的,那爲什麼現在變成了systemd
呢?
其實這裏的systemd
就是init
;我們可以看到他是所有進程的父進程;
我試過kill
掉這個進程但是哪怕是kill -9
都殺不掉這個進程;
4.1關於終端進程
在剛纔測試孤兒進程的時候我發現了,我每打開一個終端就是一個進程;
那我如果kill
掉終端這個進程會怎麼樣;
我們先查一下終端進程的id;
使用我們的top
命令,我們就能找到一個COMMAND
爲deepin-terminal
的進程我們在kill
掉這個進程以後我們的終端就關閉了;
關於NI
和PR
還有負載,我將重新寫一篇博客;