Linux命令系列之top——裡面藏著很多鮮為人知的寶藏知識

2022-10-06 06:01:18

Linux命令系列之top——裡面藏著很多鮮為人知的寶藏知識

簡介

top命令是我們經常用來檢視系統資訊的一個指令,它提供了一個動態的而且是實時的藉口幫助我們去檢視系統執行時的程序、執行緒和系統引數的資訊。

top命令輸出內容詳細剖析

首先我們先看一下top命令的輸出結果:

我們現在一一分析這些欄位的含義:

第一行

  • 12:53:04表示當前時間,也就是當前真實的時間。

  • up 157 days 13:35,表示這個系統從啟動到現在的時間,上圖顯示的含義就是這個系統從157天13個小時35分鐘以前就啟動了。

  • 5 users 表示當前在使用這個機器的使用者數量。

  • load average: 0.00, 0.00, 0.00 ,這個值表示系統過去1分鐘,5分鐘,15分鐘的系統負載。現在有一個問題就是,什麼是這裡談到的系統負載。所謂系統負載,我們拿一分鐘來舉例子,我們將一分鐘一個CPU時間定義為t,在這一分鐘之內總共消耗的CPU時間為c,那麼在這一分鐘之內的負載為\(\frac{c}{t}\),需要注意的是這個消耗的CPU時間c是可以大於t的,因為一個程式可能使用了多個CPU(並行程式,也可能是多個程序同時在使用不同的CPU)。

比如上面圖中的1分鐘內的負載大約是10,那麼在過去的一分鐘之內系統當中各種程式所消耗的CPU時間為\(c = 10.04 \times t\)。他表示的意思就是在過去的1分鐘之內,CPU時間的消耗可以看作大約有10個CPU在滿負荷運轉。注意:這裡是可以看作是10個CPU在滿負荷的運轉,其實真實情況可以是在過去的一分鐘之內有20個CPU在進行計算,然後每個CPU的計算時間為\(\frac{1}{2}t\),或者其他相同的CPU消耗情況。

第二行

  • 第二行主要表示當前系統當中任務的相關情況,所謂任務就是當前系統當中一共有多少個程序。

  • 652 totoal,這個表示當前系統當中一共有652個程序。

  • 1 runnung,表示有一個程序正在執行。

  • 651 sleeping,表示有651個程序處於睡眠狀態,也就是不需要使用CPU的狀態。

  • 0 stoped,表示有0個程序處於stopped狀態,這個狀態就是被停下來的程序,比如說通過ctrl+z讓一個程序停下來,你可以通過給這個程序傳送一個訊號SIGCONT讓這個程序恢復執行,linux當中程序的狀態變換如下所示:

  • 0 zombie,這個就表示殭屍程序的個數,這裡是0個殭屍程序,所謂殭屍程序就是一個程序執行完成了,對於C程式來說你可以理解為你的main函數執行完成了(這個不夠準確,其實main函數執行完成之後還會有其他函數需要執行,但是這裡你可以大致這麼理解),如果這個時候(函數執行完成),這個程序的父程序卻沒有接受子程序傳送給他的訊號(子程序在執行完成之後會給父程序傳送訊號,父程序需要通過wait等系統呼叫去接受這個訊號),那麼子程序就處於zombie狀態,處於這個狀態的程序就需要父程序接受它傳送的訊號,然後子程序的系統資源就可以被回收了,然後子程序會徹底消亡。

我們現在花一點時間來談一談linux當中的程序狀態。

  • Ready,當程序被建立完成之後他就處於Ready狀態,在這個狀態下的程序只差CPU了,也就是說,他現在只需要被作業系統排程獲取CPU然後他就可以執行了。

  • Running,當程序從Ready狀態獲取CPU的執行權的時候,程序就處於Running狀態,這個狀態表示程序正在執行。

  • traced,這個狀態主要是一個程序處於偵錯狀態,這個狀態需要偵錯的程序給這個被偵錯的程序傳送訊號,然後和這個程序才可以繼續執行。

  • Zombie,當程序執行完成之後,父程序接受子程序傳送的訊號之前,程序就處於這個狀態。

  • Suspended,這個狀態表示程序被掛起,當程序請求IO的時候,需要阻塞等待IO請求完成,這個時候的程序狀態就是Suspened狀態。

第三行

這一行主要是各種時間所佔的百分比的統計,這個資料的統計時間區間是,從本次重新整理到上一次重新整理之間,實在這個區間統計的資料

  • us,執行沒有指定優先順序的使用者程序所消耗的CPU時間所佔百分比,預設的終端執行的程式都是沒有指定優先順序的,我們可以使用nice這個命令來改變程式執行的優先順序:sudo nice -n -10 ./time
  • sy,執行核心程序所消耗的CPU時間所佔的百分比。
  • ni,執行指定了修改過優先順序之後的使用者程序所佔的CPU時間百分比。這裡可以結合PR和NI兩個欄位進行分析,我們現在執行sudo nice -n 10 ./a.out命令,在./a.out當中我啟動了10個死迴圈的執行緒,我們來看一下它的top輸出結果:

從上面的結果來看我們通過nice命令修改來程序優先順序,但是需要主要的是一個程序的PR值越大他的優先順序越低,NI值越大優先順序越低,也就是說我們上面實際上是降低了程序執行的優先順序了,但是我們可以看到ni的值是發生變化了的,這也印證了上面我們所談到的ni值發生變化的過程。我們再來看一下沒有設定優先順序的結果,直接執行sudo ./a.out

但是在實驗測試的過程當中發現了一個奇怪的問題,但我們提升程序的優先順序(提升優先順序需要管理員許可權)的時候ni的值沒有發生變化,因此上面所談到的ni的變化應該只適用於普通使用者的程序(因為降低優先順序不需要管理員許可權)。

  • id, idle程序執行所佔的CPU時間百分比,當系統當中沒有足夠的程序讓CPU執行的時候,idle程序會被排程到CPU上進行執行,這個idle程序是為了讓作業系統能夠良好的執行起來所設定的,idle程序主要執行HLT指令,這個指令主要是讓CPU節能,不需要CPU滿負荷運轉,因為這個時候沒有具體的程序需要執行,這個百分比越大說明系統負載越輕,CPU不繁忙。
  • wa,這個很好解釋,等待IO的時間。
  • hi,處理硬體中斷所消耗的時間。
  • si,處理軟體中斷所消耗的時間
  • st,這個時間稍微有點複雜,IBM解釋原文為:

Steal time is the percentage of time a virtual CPU waits for a real CPU while the hypervisor is servicing another virtual processor.

這個主要是虛擬機器器的虛擬CPU等待真實物理CPU的時間,可以大致認為是Ready狀態到Running狀態的等待時間,如果這個值越大說明虛擬機器器執行狀態越不好,因為它等待真實CPU的時間很長。

第四行

這一行表示的是實體記憶體的資訊,單位是KiB。

  • total, 表示一共有多少記憶體,也就是實體記憶體大小。
  • free, 表示還有多少實體記憶體沒有使用。
  • used, 表示使用了多少實體記憶體。
  • buff/cache, 表示用於用於快取的實體記憶體的大小。

第五行

這一行主要表示的是對換區的資料,所謂對換區就是當作業系統發現記憶體滿了之後,作業系統會選擇部分不常使用的頁面將它放到磁碟當中當需要使用的時候再將這部分資料從磁碟當中讀取出來。

  • total, 表示對換區的總大小。
  • free, 表示對換區當中還有多少空間沒有使用。
  • used, 表示對換區當中有多少空間被使用了。
  • 最後一項 avail Mem 是一個可用於啟動新程式的記憶體大小的估計值。

表頭內容含義

  • PID,表示程序號,就是每個程序的ID。
  • USER,就是使用者的名稱。
  • PR,優先順序值。
  • NI,nice值,通過程式給程序設定的。
  • VIRT,程序使用的虛擬記憶體的大小,單位是KiB。
  • RES,常駐記憶體的記憶體大小,單位是KiB。
  • SHR,共用記憶體的大小,單位是KiB。
  • S,表示程序的狀態,有一下幾個狀態。
    • D,不能夠中斷的睡眠狀態。
    • R,表示程式正在CPU上執行。
    • S,表示程序正在睡眠。
    • T,程序被訊號停止執行。
    • t,表示程序正在被偵錯程式追蹤,偵錯程式將這個程序停了下來。
    • Z,zombie表示是一個殭屍程序。
  • %CPU,上次一重新整理之前對應的程序對CPU的佔有率,這個值是可以突破100%的,因為一個程序可以有多個程序,比如下面這樣,我們開啟10個執行緒進行死迴圈:
#include <pthread.h>


void* func(void * args) {
  while (1)
  {
    /* code */
  }
  
}

int main() {
  #define num_threads 10
  pthread_t t[num_threads];
  for(int i = 0; i < num_threads; i++) {
    pthread_create(&t[i], NULL, func, NULL);
  }
  for (size_t i = 0; i < num_threads; i++)
  {
    pthread_join(t[i], NULL);
  }
  
  return 0;
}

執行上面的程式之後,top的輸出結果如下所示:

從上面的這個結果我們可以知道CPU的佔有率是可以超過%100的,這個值的計算主要是在重新整理之間內一個程序消耗的CPU時間和在這段時間內一個CPU能夠產生的CPU時間的比值。

  • %MEM,這個主要是程序使用的記憶體佔用實際的可用的實體記憶體的比例。
  • TIME+,這個表示自從程序啟動以來累計消耗的CPU時間。
  • COMMAND,這個表示啟動程序的時候執行的命令。

top命令互動操作

  • c,詳細顯示命令列的內容,你在互動模式下直接按下鍵盤上的c即可。

  • o,在互動模式下先按下鍵盤上的o,然後就可以輸入過濾條件,在這裡掩飾的是COMMAND=a.out的程序:

  • k,shell給我們提供了一個非常方便的操作我們可以在互動模式下選擇我們想要殺死的程序,比如在下圖當中我們殺死程序135020。

我們先在互動模式下先按下鍵盤上的k,然後輸入程序號,然後輸入回車,再輸入想傳送的訊號型別。

輸入程序號

再輸入想要傳送的訊號:

這裡可以輸入代表訊號的數位,也可以輸入代表訊號的名字,不同的訊號的名字和代表輸入如下:

 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX
  • u,通過使用者過濾,在互動模式下按下鍵盤上的u鍵,然後就可以輸入你想看那個使用者的程序,輸入對應的使用者名稱稱即可,比如說看root使用者的程序:

然後我們就只能夠看到root使用者的程序了。

  • h,檢視幫助資訊:

  • i,過濾掉CPU利用率很低的程序,很多時候我們在進行系統分析的時候需要去判斷那個程序CPU佔有率高,因此i是一個非常有效的方式過濾掉干擾程序。


以上就是本篇文章的所有內容了,我是LeHung,我們下期再見!!!更多精彩內容合集可存取專案:https://github.com/Chang-LeHung/CSCore

關注公眾號:一無是處的研究僧,瞭解更多計算機(Java、Python、計算機系統基礎、演演算法與資料結構)知識。