對於桌面使用者來說,資源監控是件比較重要的事情。我們可以以此明白系統的效能瓶頸以計劃如何最佳化系統,定位記憶體溢位等問題。但問題是,我們該用哪個軟體或什麼軟體才能滿足我們的目的呢?在這麼多監控軟體中,大多數人使用top工具(procps包的一個元件)。Top給我們提供了用系統快照來監控系統資源使用率。在這篇文章中,所有的內容都是基於linux核心2.6.×的procps3.2.5元件包來講的。
現在,假設你已經在你的linux環境中安裝並執行了procps元件包。你不需要有任何top命令的使用經驗,但是你如果已經簡單用過一下了,就更好了。
下面是一些挑戰:
A.互動還是批處理模式?
預設情況下,Top 被呼叫時使用互動模式。在此模式下,Top 無限期執行,並可以透過按鍵重新定義 Top 的執行方式。但是,有時你需要對 Top 的輸出進行後續處理,但這在此模式下難以實現。解決方法?使用批處理模式。
1
$ top -b
你將獲得類似下面的輸出:
top - 15:22:45 up 4:19, 5 users, load average: 0.00, 0.03, 0.00
Tasks: 60 total, 1 running, 59 sleeping, 0 stopped, 0 zombie
Cpu(s): 3.8% us, 2.9% sy, 0.0% ni, 89.6% id, 3.3% wa, 0.4% hi, 0.0% si
Mem: 515896k total, 495572k used, 20324k free, 13936k buffers
Swap: 909676k total, 4k used, 909672k free, 377608k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 16 0 1544 476 404 S 0.0 0.1 0:01.35 init
2 root 34 19 0 0 0 S 0.0 0.0 0:00.02 ksoftirqd/0
3 root 10 -5 0 0 0 S 0.0 0.0 0:00.11 events/0
哈,等等,它是不斷重複執行的,同互動模式一樣。不用擔心,你可以使用 -n 限制重複數量。所以,如果你希望獲得一次性結果,鍵入:
$ top -b -n 1
這一模式的真正優勢在於你可以很容易的與 at 或 cron 命令結合。它們的結合,使得 Top 可以在特定時間對資源使用狀態進行快照。例如,使用 at ,我們可以設定 top 在一分鐘之後執行。
$ cat ./test.at
TERM=linux top -b -n 1 >/tmp/top-report.txt
$ at -f ./test.at now+1minutes
細心的讀者可能會問“在建立新任務時,為什麼我需要在呼叫 Top 之前設定環境變數 TERM?”。答案是,Top 執行時需要此變數,但“at”在定時呼叫時並不會保留它。同上面那樣簡單的設定可以確保 Top 正常執行。
B.如何監控制定程序?
有時,我們只對幾個程序感興趣,可能只是全部程序中的4個或5個。例如,如果你想要監測程序標識(PID)為4360和4358的程序,你需要鍵入:
$ top -p 4360,4358
或
$ top -p 4360 -p 4358
看起來很簡單,只需要使用 -p 列出所有需要的 PID,並使用逗號間隔或簡單的多次使用 -p即可。
另一種可能是監測擁有特定使用者標識(UID)的程序。應對此需求,你可以使用 -u 或 -U 選項。假設使用者“johndoe”的 UID 為500,鍵入:
$ top -u johndoe
OR
$ top -u 500
或
$ top -U johndoe
結論是,你既可以純使用使用者名稱,也可使用數字 UID。“-u,-U?這兩者不同?”是的。同多數其它 GNU 工具一樣,選項是大小寫敏感的。-U 意味著 Top 將會搜尋有效的、真實的、被儲存的以及檔案系統的 UID 進行匹配,而 -u 僅匹配有效的使用者id。要知道,每一個 *nix 程序在執行時都是用有效使用者標識(effective UID),而其中有些並不等同真實使用者標識。多數情況是,對類似檔案系統許可權或作業系統功能這項的有效使用者標識感興趣的人將會檢查它,而不是 UID。
不同於 -p 僅用於命令列選項,-U 和 -u 都可以在互動模式中使用。同你猜測的一樣,鍵入‘U’或‘u’可以依據使用者名稱過濾程序。同樣的規則依然適用,‘u’為有效使用者標識,‘U’為 真實/有效/儲存/檔案系統使用者名稱。你將被要求鍵入使用者名稱或數字 UID。
C.快熟還是緩慢更新?
在回答這個問題之前,讓我們先簡單介紹一下,Top 是如何執行的。這裡,Strace 能夠幫助你:
$ strace -o /tmp/trace.txt top -b -n 1
使用你偏愛的文字編輯器開啟 /tmp/trace.txt。你怎麼想?一次呼叫有太多的活要做了,反正我是這麼想的。Top 在每次遍歷中必做的工作之一就是開啟很多檔案,並解析其內容,可以看看次數:
$ grep open( /tmp/hasil.txt | wc -l
舉例而言,我的 Linux 中,這個數量是304.仔細觀察就會發現,Top 遍歷 /proc 資料夾,以收集程序資訊。/proc 本身是一個虛擬檔案系統,意味著它並非存在於真實硬碟之中,而是由 Linux 核心憑空建立,儲存在記憶體中的。在資料夾中,如/proc/2097(2097為 PID),Linux 核心將與之關聯的資訊列印到此檔案中,而這裡就是 Top 的訊息來源。
同時試一下:
$ time top -b -n 1
這樣你就能瞭解到 Top 單輪工作有多快了。在我的系統中,大約為0.5-0.6秒。看“real”欄位,不是“user”或“system”欄位,因為“real”欄位反應了 Top 工作需要的總時間。
所以,有了這個認知之後,使用適度的更新間隔是明智的。基於檔案系統訪問記憶體也是需要時間的。經驗法則是,對於多數使用者來說,1到3秒的間隔就足夠了。在命令列中使用-d,或在互動模式下按下“s”以設定。你可以使用類似2.5,4.1這樣的小樹。
什麼時候我們需要快於1秒的更新?
時間段內需要更多的樣本。應對這點要求,最好使用批處理模式,並將標準輸出重定向到檔案中,以便更好的分析。
你並不在意 Top 消耗的額外CPU負荷。是的,雖然它很小,它依然需要負荷。如果你的 Linux 系統相對比較空閒,隨意使用短間隔,如果不是,最好為重要的任務保留你的 CPU 時間。
一個減少 Top 工作的辦法是隻監測特定的幾個 PID。這樣,Top 無需遍歷 /proc 下所有的子資料夾。使用者名稱過濾呢?並不會變得更好。使用者名稱過濾會給Top帶來額外工作量,因此將其與短間隔聯合將會增加 CPU 負荷。
當然,當你需要強制更新時,按下 Space 鍵,Top 將會重新整理統計。
D.我們需要的欄位
預設時,Top 啟動後會顯示下面的任務屬性:
欄位 描述
PID : 程序 ID
USER : 有效使用者 ID
PR : 動態優先值
NI : 良好值,也被稱為基本優先順序
VIRT : 任務虛擬大小。包括程序的可執行二進位制檔案大小,資料區大小以及所有已載入的共享庫的大小。
RES : 目前任務記憶體消耗。存入交換分割槽的部分並不包含。
SHR : 一些記憶體區域可能由兩個或多個任務分享,此欄位反應這些共享區域。例如共享庫以及 Sysv 共享記憶體。
S : 任務狀態
%CPU : Top 螢幕更新時專用於執行任務的CPU 時間百分比。
%MEM : 任務當前記憶體消耗的百分比
TIME+ : 在任務啟動後消耗的總CPU時間。"+" sign means it is displayed with hundreth of a second granularity. 預設時,TIME/TIME+ 不會計入已經關閉的任務子程序。
COMMAND : 顯示程式名。
不止這些。下面我介紹一些你可能會用到的列:
列 描述
nFLT ('u'鍵)
程序啟動以來重大頁面錯誤(page fault)的個數。準確地說,頁面錯誤是由於程序訪問它的地址空間內不存在的頁面引起的。“重大”的頁面錯誤是指核心需要訪問磁碟來使得該頁面有效。相反,小型頁面錯誤是指核心只需要在記憶體中分配頁面而不用讀磁碟。
例如,假設程式ABC的大小為8KB,頁面大小為4KB。當程式讀進記憶體的時候,發生了兩次重大的頁面錯誤(2*4KB)。程式本身分配了8KB空間當作臨時資料。因此,還會有兩次小型頁面錯誤。
nFLT過高可能意味著:
程序從磁碟讀取大量資源。The task is aggressively load some portions of its executable or library from the disk.
程序訪問了一個已經交換到磁碟的頁面。
當程序第一次執行時,看到大量重大頁面錯誤很正常。下次執行的時候,由於快取已經分配好了,你很可能看到"0"次或者很小的 nFLT。但是,如果一個程式頻繁地觸發重大頁面錯誤,很有可能是你目前安裝的記憶體不夠那個程式使用。
nDRT ('v'鍵)
上次頁面寫入磁碟以來,髒頁面的數目。
什麼是髒頁面?先看一點背景知識。大家都知道,Linux使用了快取系統,所以從磁碟讀取的資料也會被快取到記憶體中。這樣做的優點是,後續的對這個磁碟塊的讀操作可以直接從記憶體中取資料,因而速度更快。
但這也是有代價的。如果緩衝區的內容被修改了,那麼就需要進行同步。因此,被更改的緩衝區(髒頁面)必需寫回到磁碟中。同步失敗則可能導致磁碟上的資料不一致。
在負載不重的系統中,nDRT 通常小於10(大約估計)或者為0。如果你的系統通常大於10,則有可能:
程序正在往磁碟寫入大量資料。磁碟I/O經常跟不上緩衝區的速度。
磁碟I/O擁塞,因此即使程序修改了很小部分檔案,也必需等待一段時間才能完成同步。擁塞出現在很多程序同時訪問磁碟而快取命中率低的情況下(譯者注:FTP服務的典型情況)。
現在的話,(1) 不太可能出現,因為I/O速度越來越快,需要更少的CPU(DMA技術的出現)。所以 (2) 出現的機率更高。
注意:在 2.6.x 核心中, 不知道為什麼,這個列的值總是0。
P ('j'鍵)
上次使用的CPU。這個列只在SMP環境中有意義。這裡的SMP指超執行緒,多核或者多CPU架構。如果你只有一個CPU(不是多核,沒有超執行緒),這個列總是顯示0。
在SMP系統中,即使這個列有幾次改變,也不要吃驚。這意味著,Linux 核心嘗試將你的程序移到另一個負載更少的CPU。
CODE ('r'鍵) 和 DATA ('s'鍵)
CODE 只是反映了你程式程式碼的大小,DATA反映了你資料段(棧,堆,變數,不包含共享庫) 的大小。單位都是KB。
DATA可以顯示你的程式分開了多少記憶體。有時,也可以用來協助分析記憶體洩漏。當然,你需要更好的工具,如使用 valgrind 來檢視每次的記憶體分配。如果DATA不斷增長,則很有可能出現了記憶體洩漏。
注意:DATA, CODE, SHR, SWAP, VIRT, RES 都是使用頁面大小(Intel架構上為4KB)來衡量。只讀資料段也包含在CODE的大小中,因而有時候CODE比實現的段要大。
SWAP ('p'鍵)
已經進行交換的程序記憶體映像大小。這個列有時很讓人疑惑:
邏輯上,你可能期望這個列顯示你的程式實際上是完全進行交換,還是部分交換了,交換了多少。但是事實上不是。即使"Swap used" 列顯示為0,你仍然可以很吃驚地發現所有程序的SWAP列都大於0。到底是為什麼呢?
這是由於 top 命令使用如下的計算公式:
VIRT = SWAP + RES or equal
SWAP = VIRT - RES
前面說過,VIRT 包含了程序的地址空間裡面的所有東西:記憶體中的,已經進行交換的,尚未從磁碟讀取的。RES 代表了程序佔用的全部記憶體大小。所以,這裡的SWAP代表了已經進行交換的全部資料,以及尚未從磁碟讀取的資料。不要被SWAP這個名字迷惑了,它代表的不只是已經交換的資料。
要顯示以上的列,在互動模式下按 'f' 鍵,然後再按相應的鍵。按一下顯示指定的列,再按一下隱藏該列。要確定當前顯示的是哪些列,只需看第一行的字母(在"Current Fields"的右邊)。大寫字母表示顯示了該列,小寫表示隱藏。你選好以後,按回車即可。
排序使用了類似的方法。按 'O' (大寫),然後再按相應的鍵。即使記不住那些按鍵也沒關係,top 會顯示出來。新的排序鍵將標上星號,相應的字母會變成大寫,很直觀。選好以後,記得按回車。
E.多檢視比單個檢視更好嗎?
在不同的情況下,有時候我們想監視不同的系統屬性。例如,你想同時監控CPU的百分比和CPU被所有任務消耗的時間。在另一段時間,你想監控常駐記憶體和所有任務的總頁面故障。快速按‘F’鍵然後切換介面?我想這也太不明智了吧。
為什麼不試試多檢視視窗模式呢?按‘A’(大寫)切換到多視窗介面。預設的,你將會看到4個不同的系列的欄位組。每個欄位組有預設的標籤/名稱:
第一欄位組: Def
第二欄位組: Job
第三欄位組: Mem
第四欄位組: Usr
第一欄位組就是你在單一檢視視窗所常見的組,而其餘的組會被隱藏。內建多檢視視窗模式,所有可用的視窗透過按‘a’或者‘w’迴圈。注意,切換到其他視窗時會改變活動視窗(也稱為當前視窗)。假如你不確定哪一個是活動視窗的話,只需要看一下top展示的第一行(在當前時間欄位的左邊)。另一個改變活動視窗的方法是透過按‘G’緊跟著輸入數字(1到4)。
活動視窗是針對使用者輸入的,因此在開始幹活之前確定選好了你偏好的介面。然後,你可以在單一視窗模式下愛幹嘛幹嘛。在這種情況你一般想自定義欄位展示,那麼你只需要按‘f’然後開始自定義。
假如你認為第四欄位組太多的話,你只需要切換到欄位組然後按‘-’隱藏。請注意,即使你隱藏了當前的欄位組,那並不以意味著你同時改變了活動組。再次按‘-’的話,當前組就可見了。
如果你想操作多檢視視窗模式,再次按‘A’鍵。那樣也將使得活動組成為了單一檢視視窗模式的新的欄位組。
F. "我的Linux主機上怎麼會只有很少的空閒記憶體?"
有同樣的問題? 不管你在主機板上增加多少記憶體,你都會很快發現空閒記憶體減少的非常迅速. 空閒記憶體算錯了? 不!
在回答這個之前, 先檢視一下top命令頂部顯示的記憶體概要 (有可能你需要按 'm'來顯示出來). 在這裡,你可以看到兩個區域: 緩衝(buffers)和快取(cached)。 "緩衝(Buffers)" 代表有多少記憶體用來快取磁碟塊 "快取(Cached)" 有一點類似 "緩衝(Buffers)", 只是僅僅從檔案讀取快取頁面. 想透徹瞭解這部分,建議讀一下Linux核心的書比如Robert M.Love寫的《Linux Kernel Development》。
這足夠了解緩衝(buffers)和快取(cached)代表系統快取. 他們會根據linux核心機制動態增加或減少。
除去被快取的消耗,程式和程式碼同樣要佔據RAM. 所以,最終空閒記憶體顯示的是RAM中不被快取和程式/程式碼佔用的部分 一般來說,你也可以考慮快取區域為另一部分“空閒”RAM,如果程式需要更多記憶體它會減少
從程序的角度來看,你可能想知道哪個區域代表真實的記憶體消耗,VIRT(virtual memory usage )區域? 當然不是! 回顧一下,這個區域代表了程序地址空間裡一切,包括相關的庫。閱讀top命令的原始碼和proc.txt (在核心程式碼樹中的Documentation/filesystem 資料夾內), 我的結論是RSS欄位是程序記憶體消耗的最好的描述.我說“最好的”是因為你可以考慮它是近似而不是所有時間100%準確。
G.使用數個儲存的配置
希望儲存多個不同的配置檔案,以便於輕鬆的切換預配置檢視?只需要建立一個 Top 二進位制檔案的軟連線到你喜歡的名字:
# ln -s /usr/bin/top /usr/bin/top-a
然後執行新的“top-a”。調整完畢後鍵入‘W’儲存配置,它將被儲存到 ~/.top-arc(格式為你的 Top 別名+rc)。
這樣,執行原來的 Top 可以使用之前的檢視,而 top-a 則使用第二個,依次類推。
H.總結
有很多竅門使用top會更加高效。關鍵是知道你真正需要的是什麼和可能的對Linux低階別原理的一般理解。統計並不總是正確,但至少有助於總體衡量。所有這些數字收集自 /proc,因此首先確保它已掛載!
參考:
Understanding The Linux Kernel,第二版。
核心原始碼樹裡的/filesystems/proc.txt文件。
Linux 核心原始碼。