NO IMAGE

top命令是Linux下常用的效能分析工具,能夠實時顯示系統中各個程序的資源佔用狀況,類似於Windows的工作管理員。下面詳細介紹它的使用方法。

top – 01:06:48 up 1:22, 1 user, load average: 0.06, 0.60, 0.48
Tasks: 29 total,   1 running, 28 sleeping,   0 stopped,   0 zombie
Cpu(s): 0.3% us, 1.0% sy, 0.0% ni, 98.7% id, 0.0% wa, 0.0% hi, 0.0% si
Mem:    191272k total,   173656k used,    17616k free,    22052k buffers
Swap:   192772k total,        0k used,   192772k free,   123988k cached

   PID USER      PR NI VIRT RES SHR S %CPU %MEM    TIME COMMAND
1379 root      16   0 7976 2456 1980 S 0.7 1.3   0:11.03 sshd
14704 root      16   0 2128 980 796 R 0.7 0.5   0:02.72 top
     1 root      16   0 1992 632 544 S 0.0 0.3   0:00.90 init
     2 root      34 19     0    0    0 S 0.0 0.0   0:00.00 ksoftirqd/0
     3 root      RT   0     0    0    0 S 0.0 0.0   0:00.00 watchdog/0

統計資訊區

前五行是系統整體的統計資訊。第一行是任務佇列資訊,同 uptime 命令的執行結果。其內容如下:

01:06:48 當前時間
up 1:22 系統執行時間,格式為時:分
1 user 當前登入使用者數
load average: 0.06, 0.60, 0.48 系統負載,即任務佇列的平均長度。
三個數值分別為 1分鐘、5分鐘、15分鐘前到現在的平均值。

第二、三行為程序和CPU的資訊。當有多個CPU時,這些內容可能會超過兩行。內容如下:

Tasks: 29 total 程序總數
1 running 正在執行的程序數
28 sleeping 睡眠的程序數
0 stopped 停止的程序數
0 zombie 殭屍程序數
Cpu(s): 0.3% us 使用者空間佔用CPU百分比
1.0% sy 核心空間佔用CPU百分比
0.0% ni 使用者程序空間內改變過優先順序的程序佔用CPU百分比
98.7% id 空閒CPU百分比
0.0% wa 等待輸入輸出的CPU時間百分比
0.0% hi  
0.0% si  

最後兩行為記憶體資訊。內容如下:

Mem: 191272k total 實體記憶體總量
173656k used 使用的實體記憶體總量
17616k free 空閒記憶體總量
22052k buffers 用作核心快取的記憶體量
Swap: 192772k total 交換區總量
0k used 使用的交換區總量
192772k free 空閒交換區總量
123988k cached 緩衝的交換區總量。
記憶體中的內容被換出到交換區,而後又被換入到記憶體,但使用過的交換區尚未被覆蓋,
該數值即為這些內容已存在於記憶體中的交換區的大小。
相應的記憶體再次被換出時可不必再對交換區寫入。

程序資訊區

統計資訊區域的下方顯示了各個程序的詳細資訊。首先來認識一下各列的含義。

序號 列名 含義
a PID 程序id
b PPID 父程序id
c RUSER Real user name
d UID 程序所有者的使用者id
e USER 程序所有者的使用者名稱
f GROUP 程序所有者的組名
g TTY 啟動程序的終端名。不是從終端啟動的程序則顯示為 ?
h PR 優先順序
i NI nice值。負值表示高優先順序,正值表示低優先順序
j P 最後使用的CPU,僅在多CPU環境下有意義
k %CPU 上次更新到現在的CPU時間佔用百分比
l TIME 程序使用的CPU時間總計,單位秒
m TIME 程序使用的CPU時間總計,單位1/100秒
n %MEM 程序使用的實體記憶體百分比
o VIRT 程序使用的虛擬記憶體總量,單位kb。VIRT=SWAP RES
p SWAP 程序使用的虛擬記憶體中,被換出的大小,單位kb。
q RES 程序使用的、未被換出的實體記憶體大小,單位kb。RES=CODE DATA
r CODE 可執行程式碼佔用的實體記憶體大小,單位kb
s DATA 可執行程式碼以外的部分(資料段 棧)佔用的實體記憶體大小,單位kb
t SHR 共享記憶體大小,單位kb
u nFLT 頁面錯誤次數
v nDRT 最後一次寫入到現在,被修改過的頁面數。
w S 程序狀態。
D=不可中斷的睡眠狀態
R=執行
S=睡眠
T=跟蹤/停止
Z=殭屍程序
x COMMAND 命令名/命令列
y WCHAN 若該程序在睡眠,則顯示睡眠中的系統函式名
z Flags 任務標誌,參考 sched.h

預設情況下僅顯示比較重要的 PID、USER、PR、NI、VIRT、RES、SHR、S、%CPU、%MEM、TIME 、COMMAND 列。可以通過下面的快捷鍵來更改顯示內容。

更改顯示內容

通過 f 鍵可以選擇顯示的內容。按 f 鍵之後會顯示列的列表,按 a-z 即可顯示或隱藏對應的列,最後按回車鍵確定。

按 o 鍵可以改變列的顯示順序。按小寫的 a-z 可以將相應的列向右移動,而大寫的 A-Z 可以將相應的列向左移動。最後按回車鍵確定。

按大寫的 F 或 O 鍵,然後按 a-z 可以將程序按照相應的列進行排序。而大寫的 R 鍵可以將當前的排序倒轉。

命令使用

1. 工具(命令)名稱
top
2.工具(命令)作用
顯示系統當前的程序和其他狀況; top是一個動態顯示過程,即可以通過使用者按鍵來不斷重新整理當前狀態.如果在前臺執行該命令,它將獨佔前臺,直到使用者終止該程式為止. 比較準確的說,top命令提供了實時的對系統處理器的狀態監視.它將顯示系統中CPU最“敏感”的任務列表.該命令可以按CPU使用.記憶體使用和執行時間對任務進行排序;而且該命令的很多特性都可以通過互動式命令或者在個人定製檔案中進行設定. 
3.環境設定
在Linux下使用。
4.使用方法
4.1使用格式
top [-] [d] [p] [q] [c] [C] [S] [s] [n] 
4.2引數說明
d 指定每兩次螢幕資訊重新整理之間的時間間隔。當然使用者可以使用s互動命令來改變之。
p 通過指定監控程序ID來僅僅監控某個程序的狀態。
q該選項將使top沒有任何延遲的進行重新整理。如果呼叫程式有超級使用者許可權,那麼top將以儘可能高的優先順序執行。
S 指定累計模式
s 使top命令在安全模式中執行。這將去除互動命令所帶來的潛在危險。
i 使top不顯示任何閒置或者僵死程序。
c 顯示整個命令列而不只是顯示命令名
4.3其他
  下面介紹在top命令執行過程中可以使用的一些互動命令。從使用角度來看,熟練的掌握這些命令比掌握選項還重要一些。這些命令都是單字母的,如果在命令列選項中使用了s選項,則可能其中一些命令會被遮蔽掉。
  Ctrl L 擦除並且重寫螢幕。
  h或者? 顯示幫助畫面,給出一些簡短的命令總結說明。
  k 終止一個程序。系統將提示使用者輸入需要終止的程序PID,以及需要傳送給該程序什麼樣的訊號。一般的終止程序可以使用15訊號;如果不能正常結束那就使用訊號9強制結束該程序。預設值是訊號15。在安全模式中此命令被遮蔽。
  i 忽略閒置和僵死程序。這是一個開關式命令。
  q 退出程式。
  r 重新安排一個程序的優先順序別。系統提示使用者輸入需要改變的程序PID以及需要設定的程序優先順序值。輸入一個正值將使優先順序降低,反之則可以使該程序擁有更高的優先權。預設值是10。
  S 切換到累計模式。
  s 改變兩次重新整理之間的延遲時間。系統將提示使用者輸入新的時間,單位為s。如果有小數,就換算成m s。輸入0值則系統將不斷重新整理,預設值是5 s。需要注意的是如果設定太小的時間,很可能會引起不斷重新整理,從而根本來不及看清顯示的情況,而且系統負載也會大大增加。
  f或者F 從當前顯示中新增或者刪除專案。
  o或者O 改變顯示專案的順序。
  l 切換顯示平均負載和啟動時間資訊。
  m 切換顯示記憶體資訊。
  t 切換顯示程序和CPU狀態資訊。
  c 切換顯示命令名稱和完整命令列。
  M 根據駐留記憶體大小進行排序。
  P 根據CPU使用百分比大小進行排序。
  T 根據時間/累計時間進行排序。
     W 將當前設定寫入~/.toprc檔案中。這是寫top配置檔案的推薦方法。


 

原文地址

用ps 的 – l 選項,得到更詳細的程序資訊:

(1)F(Flag):一系列數字的和,表示程序的當前狀態。這些數字的含義為:

       00:若單獨顯示,表示此程序已被終止。

       01:程序是核心程序的一部分,常駐於系統主存。如:sched,vhand,bdflush。

       02:Parent is tracing process.

       04 :Tracing parent’s signal has stopped the process; the parent is waiting ( ptrace(S)).

       10:程序在優先順序低於或等於25時,進入休眠狀態,而且不能用訊號喚醒,例如在等待一個inode被建立時。

       20:程序被裝入主存(primary memory)

       40:程序被鎖在主存,在事務完成前不能被置換。

 

(2) 程序狀態:S(state)

       O:程序正在處理器執行,這個狀態從來木見過.

       S:休眠狀態(sleeping)

       R:等待執行(runable)R Running or runnable (on run queue) 程序處於執行或就緒狀態

       I:空閒狀態(idle)

       Z:殭屍狀態(zombie)   

       T:跟蹤狀態(Traced)

       B:程序正在等待更多的記憶體頁

       D:不可中斷的深度睡眠,一般由IO引起,同步IO在做讀或寫操作時,cpu不能做其它事情,只能等待,這時程序處於這種狀態,如果程式採用非同步IO,這種狀態應該就很少見到了

 

(3)C(cpu usage):cpu利用率的估算值

 

 

1.2 使用Top命令中的S 欄位

pid user      pr  ni  virt  res  shr s %cpu %mem    time   command                                

11423 oracle    16   0  627m 170m 168m R   32  9.0   4110:21 oracle                                

 3416 oracle    15   0  650m 158m 138m S    0  8.4   0:07.12 oracle                                 

11167 oracle    15   0  626m 151m 149m S    0  8.0 400:20.77 oracle                                

11429 oracle    15   0  626m 148m 147m S    0  7.9 812:05.71 oracle                                

 3422 oracle    18   0  627m 140m 137m S    0  7.4   1:12.23 oracle                                

 1230 oracle    15   0  639m 107m  96m S    0  5.7   0:10.00 oracle                                

  637 oracle    15   0  629m  76m  73m S    0  4.0   0:04.31 oracle                     

 

 

二.  程序狀態說明

2.1  R (task_running) : 可執行狀態

       只有在該狀態的程序才可能在CPU上執行。而同一時刻可能有多個程序處於可執行狀態,這些程序的task_struct結構(程序控制塊)被放入對應CPU的可執行佇列中(一個程序最多隻能出現在一個CPU的可執行佇列中)。程序排程器的任務就是從各個CPU的可執行佇列中分別選擇一個程序在該CPU上執行。

       很多作業系統教科書將正在CPU上執行的程序定義為RUNNING狀態、而將可執行但是尚未被排程執行的程序定義為READY狀態,這兩種狀態在linux下統一為 TASK_RUNNING狀態。

 

2.2  S (task_interruptible): 可中斷的睡眠狀態

       處於這個狀態的程序因為等待某某事件的發生(比如等待socket連線、等待訊號量),而被掛起。這些程序的task_struct結構被放入對應事件的等待佇列中。當這些事件發生時(由外部中斷觸發、或由其他程序觸發),對應的等待佇列中的一個或多個程序將被喚醒。

       通過ps命令我們會看到,一般情況下,程序列表中的絕大多數程序都處於task_interruptible狀態(除非機器的負載很高)。畢竟CPU就這麼一兩個,程序動輒幾十上百個,如果不是絕大多數程序都在睡眠,CPU又怎麼響應得過來。

 

2.3  D (task_uninterruptible): 不可中斷的睡眠狀態

       與task_interruptible狀態類似,程序處於睡眠狀態,但是此刻程序是不可中斷的。不可中斷,指的並不是CPU不響應外部硬體的中斷,而是指程序不響應非同步訊號。
       絕大多數情況下,程序處在睡眠狀態時,總是應該能夠響應非同步訊號的。但是uninterruptible sleep 狀態的程序不接受外來的任何訊號,因此無法用kill殺掉這些處於D狀態的程序,無論是”kill”, “kill -9″還是”kill -15″,這種情況下,一個可選的方法就是reboot。

 

       處於uninterruptible sleep狀態的程序通常是在等待IO,比如磁碟IO,網路IO,其他外設IO,如果程序正在等待的IO在較長的時間內都沒有響應,那麼就被ps看到了,同時也就意味著很有可能有IO出了問題,可能是外設本身出了故障,也可能是比如掛載的遠端檔案系統已經不可訪問了.

 

       而task_uninterruptible狀態存在的意義就在於,核心的某些處理流程是不能被打斷的。如果響應非同步訊號,程式的執行流程中就會被插入一段用於處理非同步訊號的流程(這個插入的流程可能只存在於核心態,也可能延伸到使用者態),於是原有的流程就被中斷了。

       在程序對某些硬體進行操作時(比如程序呼叫read系統呼叫對某個裝置檔案進行讀操作,而read系統呼叫最終執行到對應裝置驅動的程式碼,並與對應的物理裝置進行互動),可能需要使用task_uninterruptible狀態對程序進行保護,以避免程序與裝置互動的過程被打斷,造成裝置陷入不可控的狀態。這種情況下的task_uninterruptible狀態總是非常短暫的,通過ps命令基本上不可能捕捉到。

 

       我們通過vmstat 命令中procs下的b 可以來檢視是否有處於uninterruptible 狀態的程序。 該命令只能顯示數量。

 

       In computer operating systems terminology, a sleeping process can either be interruptible (woken via signals) or uninterruptible (woken explicitly). An uninterruptible sleep state is a sleep state that cannot handle a signal (such as waiting for disk
or network IO (input/output)).

 

       When the process is sleeping uninterruptibly, the signal will be noticed when the process returns from the system call or trap.

       — 這句是關鍵。 當處於uninterruptibly sleep 狀態時,只有當程序從system 呼叫返回時,才通知signal。

 

       A process which ends up in “D” state for any measurable length of time is trapped in the midst of a system call (usually an I/O operation on a device — thus the initial in the ps output).

 

       Such a process cannot be killed — it would risk leaving the kernel in an inconsistent state, leading to a panic. In general you can consider this to be a bug in the device driver that the process is accessing.

 

2.4  T(task_stopped or task_traced):暫停狀態或跟蹤狀態

       向程序傳送一個sigstop訊號,它就會因響應該訊號而進入task_stopped狀態(除非該程序本身處於task_uninterruptible狀態而不響應訊號)。(sigstop與sigkill訊號一樣,是非常強制的。不允許使用者程序通過signal系列的系統呼叫重新設定對應的訊號處理函式。)
       向程序傳送一個sigcont訊號,可以讓其從task_stopped狀態恢復到task_running狀態。

       當程序正在被跟蹤時,它處於task_traced這個特殊的狀態。“正在被跟蹤”指的是程序暫停下來,等待跟蹤它的程序對它進行操作。比如在gdb中對被跟蹤的程序下一個斷點,程序在斷點處停下來的時候就處於task_traced狀態。而在其他時候,被跟蹤的程序還是處於前面提到的那些狀態。

      

       對於程序本身來說,task_stopped和task_traced狀態很類似,都是表示程序暫停下來。
       而task_traced狀態相當於在task_stopped之上多了一層保護,處於task_traced狀態的程序不能響應sigcont訊號而被喚醒。只能等到除錯程序通過ptrace系統呼叫執行ptrace_cont、ptrace_detach等操作(通過ptrace系統呼叫的引數指定操作),或除錯程序退出,被除錯的程序才能恢復task_running狀態。

 

 

2.5 Z (task_dead – exit_zombie):退出狀態,程序成為殭屍程序

       在Linux程序的狀態中,殭屍程序是非常特殊的一種,它是已經結束了的程序,但是沒有從程序表中刪除。太多了會導致程序表裡麵條目滿了,進而導致系統崩潰,倒是不佔用其他系統資源。    

       它已經放棄了幾乎所有記憶體空間,沒有任何可執行程式碼,也不能被排程,僅僅在程序列表中保留一個位置,記載該程序的退出狀態等資訊供其他程序收集,除此之外,殭屍程序不再佔有任何記憶體空間。

      

       程序在退出的過程中,處於TASK_DEAD狀態。在這個退出過程中,程序佔有的所有資源將被回收,除了task_struct結構(以及少數資源)以外。於是程序就只剩下task_struct這麼個空殼,故稱為殭屍。

 

       之所以保留task_struct,是因為task_struct裡面儲存了程序的退出碼、以及一些統計資訊。而其父程序很可能會關心這些資訊。比如在shell中,$?變數就儲存了最後一個退出的前臺程序的退出碼,而這個退出碼往往被作為if語句的判斷條件。
       當然,核心也可以將這些資訊儲存在別的地方,而將task_struct結構釋放掉,以節省一些空間。但是使用task_struct結構更為方便,因為在核心中已經建立了從pid到task_struct查詢關係,還有程序間的父子關係。釋放掉task_struct,則需要建立一些新的資料結構,以便讓父程序找到它的子程序的退出資訊。

 

       子程序在退出的過程中,核心會給其父程序傳送一個訊號,通知父程序來“收屍”。 父程序可以通過wait系列的系統呼叫(如wait4、waitid)來等待某個或某些子程序的退出,並獲取它的退出資訊。然後wait系列的系統呼叫會順便將子程序的屍體(task_struct)也釋放掉。

       這個訊號預設是SIGCHLD,但是在通過clone系統呼叫建立子程序時,可以設定這個訊號。

       如果他的父程序沒安裝SIGCHLD訊號處理函式呼叫wait或waitpid()等待子程序結束,又沒有顯式忽略該訊號,那麼它就一直保持殭屍狀態,子程序的屍體(task_struct)也就無法釋放掉。

 

       如果這時父程序結束了,那麼init程序自動會接手這個子程序,為它收屍,它還是能被清除的。但是如果如果父程序是一個迴圈,不會結束,那麼子程序就會一直保持殭屍狀態,這就是為什麼系統中有時會有很多的殭屍程序。

 

       當程序退出的時候,會將它的所有子程序都託管給別的程序(使之成為別的程序的子程序)。託管的程序可能是退出程序所在程序組的下一個程序(如果存在的話),或者是1號程序。所以每個程序、每時每刻都有父程序存在。除非它是1號程序。1號程序,pid為1的程序,又稱init程序。


linux系統啟動後,第一個被建立的使用者態程序就是init程序。它有兩項使命:
       1、執行系統初始化指令碼,建立一系列的程序(它們都是init程序的子孫);
       2、在一個死迴圈中等待其子程序的退出事件,並呼叫waitid系統呼叫來完成“收屍”工作;

       init程序不會被暫停、也不會被殺死(這是由核心來保證的)。它在等待子程序退出的過程中處於task_interruptible狀態,“收屍”過程中則處於task_running狀態。

 

Unix/Linux 處理殭屍程序的方法:

       找出父程序號,然後kill 父程序,之後子程序(殭屍程序)會被託管到其他程序,如init程序,然後由init程序將子程序的屍體(task_struct)釋放掉。

 

除了通過ps 的狀態來檢視Zombi程序,還可以用如下命令檢視:

[[email protected] ~]$ ps -ef|grep defun

oracle   13526 12825  0 16:48 pts/1    00:00:00 grep defun

oracle   28330 28275  0 May18 ?        00:00:00 [Xsession] <defunct>

 

殭屍程序解決辦法:

(1)改寫父程序,在子程序死後要為它收屍。

       具體做法是接管SIGCHLD訊號。子程序死後,會傳送SIGCHLD訊號給父程序,父程序收到此訊號後,執行 waitpid()函式為子程序收屍。這是基於這樣的原理:就算父程序沒有呼叫wait,核心也會向它傳送SIGCHLD訊息,儘管對的預設處理是忽略,如果想響應這個訊息,可以設定一個處理函式。

(2)把父程序殺掉。

       父程序死後,殭屍程序成為”孤兒程序”,過繼給1號程序init,init始終會負責清理殭屍程序.它產生的所有殭屍程序也跟著消失。如:

       kill -9 `ps -ef | grep “Process Name” | awk ‘{ print $3 }’`
       其中,“Process Name”為處於zombie狀態的程序名。

(3)殺父程序不行的話,就嘗試用skill -t TTY關閉相應終端,TTY是程序相應的tty號(終端號)。但是,ps可能會查不到特定程序的tty號,這時就需要自己判斷了。
(4)重啟系統,這也是最常用到方法之一。

 

 

2.6 X (task_dead – exit_dead):退出狀態,程序即將被銷燬

       程序在退出過程中也可能不會保留它的task_struct。比如這個程序是多執行緒程式中被detach過的程序。或者父程序通過設定sigchld訊號的handler為sig_ign,顯式的忽略了sigchld訊號。(這是posix的規定,儘管子程序的退出訊號可以被設定為sigchld以外的其他訊號。)
       此時,程序將被置於exit_dead退出狀態,這意味著接下來的程式碼立即就會將該程序徹底釋放。所以exit_dead狀態是非常短暫的,幾乎不可能通過ps命令捕捉到。

 

三. 程序狀態變化說明

3.1 程序的初始狀態

       程序是通過fork系列的系統呼叫(fork、clone、vfork)來建立的,核心(或核心模組)也可以通過kernel_thread函式建立核心程序。這些建立子程序的函式本質上都完成了相同的功能——將呼叫程序複製一份,得到子程序。(可以通過選項引數來決定各種資源是共享、還是私有。)
       那麼既然呼叫程序處於task_running狀態(否則,它若不是正在執行,又怎麼進行呼叫?),則子程序預設也處於task_running狀態。
       另外,在系統呼叫呼叫clone和核心函式kernel_thread也接受clone_stopped選項,從而將子程序的初始狀態置為 task_stopped。

 

3.2 程序狀態變遷

       程序自建立以後,狀態可能發生一系列的變化,直到程序退出。而儘管程序狀態有好幾種,但是程序狀態的變遷卻只有兩個方向——從task_running狀態變為非task_running狀態、或者從非task_running狀態變為task_running狀態。
       也就是說,如果給一個task_interruptible狀態的程序傳送sigkill訊號,這個程序將先被喚醒(進入task_running狀態),然後再響應sigkill訊號而退出(變為task_dead狀態)。並不會從task_interruptible狀態直接退出。

       程序從非task_running狀態變為task_running狀態,是由別的程序(也可能是中斷處理程式)執行喚醒操作來實現的。執行喚醒的程序設定被喚醒程序的狀態為task_running,然後將其task_struct結構加入到某個cpu的可執行佇列中。於是被喚醒的程序將有機會被排程執行。

 

而程序從task_running狀態變為非task_running狀態,則有兩種途徑:
       1、響應訊號而進入task_stoped狀態、或task_dead狀態;
       2、執行系統呼叫主動進入task_interruptible狀態(如nanosleep系統呼叫)、或task_dead狀態(如exit系統呼叫);或由於執行系統呼叫需要的資源得不到滿足,而進入task_interruptible狀態或task_uninterruptible狀態(如select系統呼叫)。
顯然,這兩種情況都只能發生在程序正在cpu上執行的情況下。