Linux——進程與資源利用

進程與資源利用

進程跟蹤

top命令將系統中最活躍的進程(即當前消耗CPU時間最多的那些進程)顯示在最上方。

你可以通過鍵盤向top發送命令。下面是一些比較重要的鍵盤命令

命令 含義
空格鍵 立即更新顯示內容。
M 按照當前內存使用量排序。
T 按照CPU累計使用量排序。
P 按照當前CPU使用量(默認)排序。
u 僅顯示某位用戶的進程。
f 選擇不同的統計信息來顯示。
? 爲所有top命令顯示使用情況統計。

使用lsof查看打開的文件

lsof命令列出打開的文件以及使用它們的進程。由於Unix系統大量使用文件,所以lsof在系統排錯方面是最有用的命令之一。

lsof輸出

lsof的輸出結果通常信息量很大,。這一輸出結果中包含init進程中打開的文件和運行中的vi進程:

$ lsof
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
init 1 root cwd DIR 8,1 4096 2 /
init 1 root rtd DIR 8,1 4096 2 /
init 1 root mem REG 8, 47040 9705817 /lib/i386-linux-gnu/libnss_files-2.15.so
init 1 root mem REG 8,1 42652 9705821 /lib/i386-linux-gnu/libnss_nis-2.15.so
init 1 root mem REG 8,1 92016 9705833 /lib/i386-linux-gnu/libnsl-2.15.so
--snip--
vi 22728 juser cwd DIR 8,1 4096 14945078 /home/juser/w/c
vi 22728 juser 4u REG 8,1 1288 1056519 /home/juser/w/c/f
--snip--

其中包含以下字段:

  • COMMAND:擁有文件描述符的的進程對應的命令名。
  • PIM:PID
  • USER:運行進程的用戶。
  • FD:該列包含兩種元素。本例中FD列顯示文件的作用。該列還能夠顯示打開文件的描述符。文件描述符是一個數字,進程通過它使用系統庫和內核來進行文件標識和操作。
  • TYPE:文件類型(如常規文件、目錄、套接字等)。
  • DEVICE:包含該文件的設備的主要代碼和次要代碼。
  • SIZE:文件大小
  • NODE:文件的索引節點編號。
  • NAME:文件名

lsof的使用

運行lsof有以下兩種基本方式。

  • 輸出完整的結果,然後將輸出結果通過管道命令less顯示,然後在其中搜索你想要的內容。
  • 使用命令行選項來過濾lsof的輸出結果。

下面的命令顯示/usr目錄中所有打開的文件:

$ lsof /usr

根據PID列出打開文件,使用以下命令:

$ lsof -p pid

你可以運行lsof -h查看lsof所有的選項。大部分選項和輸出格式有關。

跟蹤程序執行和系統調用

strace(系統調用跟蹤)和ltrace(系統庫跟蹤)命令能夠幫助你瞭解程序試圖執行哪些操作。

strace命令

strace能夠顯示進程涉及的所有系統調用

$ strace cat /dev/null

如果一個進程想啓動另一個進程,該進程會使用fork()系統調用來從自身創建出一個副本,然後副本調用exec()系統調用集來啓動和運行新的程序。

strace命令在fork()系統調用之後開始監控新創建的進程(即源進程的副本)。因而該命令輸出結果的一開始
幾行應該顯示execve()的執行情況,隨後是內存初始化系統調用brk()。

execve("/bin/cat", ["cat", "/dev/null"], [/* 58 vars */]) = 0
brk(0) = 0x9b65000

輸出的後續部分涉及共享庫的加載。除非你想知道加載共享庫的細節,否則你可以忽略這些信息。

ltrace命令

ltrace命令跟蹤對共享庫的調用。它的輸出結果和strace類似,所以我們在這裏提一下。但是它不跟蹤內核級的內容。請記住,共享庫調用比系統調用數量多得多。所以你有必要過濾ltrace命令的輸出結果。ltrace命令有很多選項可以幫到你。

線程

在Linux中,一些進程被細分爲更小的部分,我們稱爲線程(thread)。線程和進程很類似,它有一個標識符(即TID)。內核運行線程的方式和運行進程基本相同。但有一點不同,即進程之間不共享內存和I/O這樣的系統資源,而同一個進程中的所有線程則共享該進程佔用的系統資源和一些內存。

單線程進程和多線程進程

很多進程只有一個線程,叫單線程進程。有超過一個線程的叫多線程進程。所有進程最開始都是單線程,起始線程通常稱爲主線程。主線程隨後可能會啓動新的線程,這樣進程就變爲多線程。這個過程和進程使用fork()創建新進程類似。

多線程的主要優勢在於,當進程要做的事情很多時,多個線程可以同時在多個處理器上運行,這樣可以加快進程的運行速度。雖然你也可以同時在多個處理器上運行多個進程,但線程相對進程來說啓動更快,並且線程間通過共享的進程內存來相互通信,比進程間通過網絡和管道相互通信更加便捷高效。

一些應用程序使用線程來解決在管理多個I/O資源時遇到的問題。傳統上來說,進程有時候會使用fork()創建新的子進程來處理新的輸入輸出流。線程提供相似的機制,但卻省去了啓動新進程的麻煩。

查看線程

默認情況下,ps和top命令只顯示進程的信息。如果想查看線程的信息,可以添加一個m選項,如下例所示。

$ ps m
PID TTY STAT TIME COMMAND
3587 pts/3 - 0:00 bash➊
- - Ss 0:00 -
3592 pts/4 - 0:00 bash➋
- - Ss 0:00 -
12287 pts/8 - 0:54 /usr/bin/python /usr/bin/gm-notify➌
- - SL1 0:48 -
- - SL1 0:00 -
- - SL1 0:06 -
- - SL1 0:00 -

該例顯示進程和線程的信息。每一行有一個PID字段(其中➊、➋、➌行的PID值是數字),代表一個進程,和一般的ps輸出一樣。PID字段值爲-的那些行代表進程中的線程。本例中進程➊和➋只有一個線程,進程➌(PID值爲12287)有四個線程。

如果想要使用ps查看TID,需要使用自定義的輸出格式。下面的例子顯示PID、TID以及相關命令。

$ ps m -o pid,tid,command
PID TID COMMAND
3587 - bash
- 3587 -
3592 - bash
- 3592 -
12287 - /usr/bin/python /usr/bin/gm-notify
- 12287 -
- 12288 -
- 12289 -
- 12295 -

資源監控

測試CPU時間

如果要監控進程,可以使用top命令加-p選項,如下所示:

$ top -p pid1 [-p pid2 ...]

使用time命令可以查看命令整個執行過程中佔用的CPU時間。大部分shell提供的time命令只顯示一些基本信息,所以你可能需要運行/usr/bin/time。例如,如果要查看ls命令佔用的CPU時間,可以運行以下命令:

$ /usr/bin/time ls

time在ls結束後會顯示像下面這樣的結果,關鍵的字段我們使用粗體字標出:

0.05user 0.09system 0:00.44elapsed 31%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (125major+51minor)pagefaults 0swaps

  • user:用戶時間,指CPU用來運行程序代碼的時間,以秒爲單位。在現在的處理器中,命令的運行速度很快,有些不超過一秒,time命令會將他們四捨五入爲0。
  • system:系統時間,指內核用來執行進程任務的時間,例如讀取文件和目錄
  • elapsed:消耗時間,指進程從開始到結束的全部時間,包括CPU執行其他任務的時間。這個數字在檢測性方面不是很有幫助,不過將消耗時間減少用戶時間和系統時間所剩餘的時間,能夠讓你得知進程等待系統資源所消耗的時間。

調節進程優先級

你可以更改內核對進程的調度方式,從而增加或減少安排給進程的CPU時間。內核按照每個進程的調度優先級來運行進程,這些優先級用-20和+20之間的數字表示。有些古怪的是,-20是最高的優先級。

ps -l命令顯示當前進程的優先級,不過使用top命令更容易一點

$ top
Tasks: 244 total, 2 running, 242 sleeping, 0 stopped, 0 zombie
Cpu(s): 31.7%us, 2.8%sy, 0.0%ni, 65.4%id, 0.2%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 6137216k total, 5583560k used, 553656k free, 72008k buffers
Swap: 4135932k total, 694192k used, 3441740k free, 767640k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
28883 bri 20 0 1280m 763m 32m S 58 12.7 213:00.65 chromium-browse
1175 root 20 0 210m 43m 28m R 44 0.7 14292:35 Xorg
4022 bri 20 0 413m 201m 28m S 29 3.4 3640:13 chromium-browse
4029 bri 20 0 378m 206m 19m S 2 3.5 32:50.86 chromium-browse
3971 bri 20 0 881m 359m 32m S 2 6.0 563:06.88 chromium-browse
5378 bri 20 0 152m 10m 7064 S 1 0.2 24:30.21 compiz
3821 bri 20 0 312m 37m 14m S 0 0.6 29:25.57 soffice.bin
4117 bri 20 0 321m 105m 18m S 0 1.8 34:55.01 chromium-browse
4138 bri 20 0 331m 99m 21m S 0 1.7 121:44.19 chromium-browse
4274 bri 20 0 232m 60m 13m S 0 1.0 37:33.78 chromium-browse
4267 bri 20 0 1102m 844m 11m S 0 14.1 29:59.27 chromium-browse
2327 bri 20 0 301m 43m 16m S 0 0.7 109:55.65 unity-2d-shell

上面的輸出結果中,PR(意思是優先級)字段顯示內核當前賦予進程的調度優先級。這個數字越大,內核調用該進程的機率越小。決定內核分配給進程CPU時間的不僅僅是優先級,並且優先級在進程執行過程中也會根據其消耗的CPU時間而頻繁改變

PR字段旁邊是NI(意思是優先值)字段,顯示有關內核進程調度的少許信息,如果你想幹預內核的進程調度,這個信息會對你有用。內核使用NI值來決定進程下一次在什麼時間運行。

NI默認值是0。例如,你在後臺運行一個計算量很大的進程,且不希望它影響到前臺的交互,想讓它在其他進程空閒的時候再運行,就可以使用renice命令將NI設置爲20(pid是你要設置的進程的ID):

$ renice 20 pid

如果你是超級用戶,你可以將NI設置爲一個負數,但這並不是一個好方法,因爲系統級進程也許無法獲得足夠的CPU時間。

平均負載

CPU的性能比較容易來衡量。**平均負載(load average)**是準備就緒待執行的進程的平均數。也就是某一時刻可以使用CPU的進程數的一個估計值。只有那些真正在運行的進程才計入平均負載。

uptime的使用

uptime命令顯示三個平均負載值和內核已經運行的時長:

$ uptime
... up 91 days, ... load average: 0.08, 0.03, 0.01

以上三個數字分別代表過去1分鐘、5分鐘和15分鐘的平均負載值。

如果平均負載值接近1,說明某個進程可能完全佔用了CPU。這時可以使用top命令來查看,通常出現在列表最上方的就是那個進程。

現在很多系統有多個處理器核心(或CPU),它們使得進程能夠同時運行。如果你有兩個核心並且平均負載爲1,這意味着只有其中一個處於活躍狀態,如果平均負載爲2,說明兩個都處於忙狀態。

高負載

如果平均負載值高並且系統響應速度很慢的話,可能意味着內存性能有問題。當系統出現內存不足的情況時,內核會開始執行一個機械性的反覆動作,或者說在磁盤和內存間交換進程數據。此時很多進程會處於執行準備就緒狀態,但是可能沒有足夠內存。這種情況下,它們保持準備就緒狀態的時間要比平時久一些。

內存

查看系統內存狀態最簡單的方法之一是使用free命令,或者查看/proc/meminfo文件來了解系統內存被作爲緩存和緩衝區的實際使用情況。

內存的工作原理

CPU通過MMU(內存管理單元)將進程使用的虛擬地址轉換爲實際的內存地址。內核幫助MMU把進程使用的內存劃分爲更小的區域,我們稱爲頁面。內核負責維護一個數據結構,我們稱爲頁面表,其中包含從虛擬頁面地址到實際內存地址的映射關係。當進程訪問內存時,MMU根據此表將進程使用的虛擬地址轉換爲實際的內存地址。

進程執行時並不需要立即加載它所有的內存頁面。內核通常在進程需要的時候加載和分配內存頁面,我們稱爲按需內存分頁(on-demand paging或者demand paging)

進程是如何啓動和運行的:

  1. 內核將程序指令代碼的開始部分加載到內存頁面內。
  2. 內核可能還會爲新進程分配一些內存頁面供其運行使用。
  3. 進程執行過程中,可能代碼中的下一個指令在已加載的內存頁面中不存在。這時內核接管控制,加載需要的內存頁面,然後讓程序恢復運行。
  4. 同樣地,如果進程需要使用更多的內存,內核接管控制,並且獲得空閒的內存空間(或者騰出一些內存空間)分配給進程。

內存頁面錯誤

如果內存頁面在進程想要使用時沒有準備就緒,進程會產生內存頁面錯誤(page fault)。錯誤產生時,內核從進程接管CPU的控制權,然後使內存頁面準備就緒。內存頁面錯誤有兩種:輕微錯誤和嚴重錯誤。

輕微內存頁面錯誤

進程需要的內存頁面在主內存中但是MMU無法找到時,會產生輕微內存頁面錯誤。通常發生在進程需要更多內存時或MMU沒有足夠內存空間來爲進程存放所有頁面時。這時內核會通知MMU,並且讓進程繼續執行。輕微內存頁面錯誤不是很嚴重,在進程執行過程中可能會出現。通常你不需要對此太在意,除非是那些對性能和內存要求很高的應用。

嚴重內存頁面錯誤

嚴重內存頁面錯誤發生在進程需要的內存頁面在主內存中不存在時,意味着內核需要從磁盤或者其他低速存儲媒介中加載。太多此類錯誤會影響系統性能,因爲內核必須做大量的工作來爲進程加載內存頁面,佔用大量CPU時間,妨礙其他進程的運行。

查看內存頁面錯誤

你可以使用ps、top或time命令爲某個進程的內存頁面錯誤查找原因。下面是一個例子,列舉time命令提供的內存頁面錯誤信息。(cal命令的輸出可以忽略,我們將其重定向到/dev/null。)

$ /usr/bin/time cal > /dev/null
0.00user 0.00system 0:00.06elapsed 0%CPU (0avgtext+0avgdata 3328maxresident)k
648inputs+0outputs (2major+254minor)pagefaults 0swaps

從以上加粗的信息可以看出,程序運行過程中產生了兩個嚴重內存頁面錯誤和254個輕微內存頁面錯誤。嚴重內存頁面錯誤發生在當內核首次從磁盤加載一個程序的時候。如果再次運行該程序,你可能不會再碰到嚴重內存頁面錯誤,因爲內核可能已經將從磁盤加載的內存頁面放入緩存了。

如果你想在進程運行過程中查看產生的內存頁面錯誤,可以使用top或者ps命令。可以使用top命令加f選項設置顯示的字段,u選項顯示嚴重內存頁面錯誤的數目。(結果會顯示在一個新的列nFLT中,輕微內存頁面錯誤不顯示。)

使用ps命令時,你可以使用自定義輸出格式來查看某個進程產生的內存頁面錯誤。下面是進程20365的一個例子:

$ ps -o pid,min_flt,maj_flt 20365
PID MINFL MAJFL
20365 834182 23

MINFL和MAJFL列顯示輕微和嚴重內存頁面錯誤數目。在此基礎上,你還可以加入其他的進程選擇參數。

使用vmstat監控CPU和內存性能

在衆多系統性能監控工具中,vmstat命令是較爲陳舊的一個,但也是運行開銷最小的一個。你可以使用它來清晰地瞭解內核交換內存頁面的頻率、CPU的繁忙程度以及IO的使用情況。

通過查看vmstat的輸出結果能夠獲得很多有用的信息。下面是vmstat 2命令的輸出結果,統計信息每2秒刷新一次:

$ vmstat 2
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
2 0 320416 3027696 198636 1072568 0 0 1 1 2 0 15 2 83 0
2 0 320416 3027288 198636 1072564 0 0 0 1182 407 636 1 0 99 0
1 0 320416 3026792 198640 1072572 0 0 0 58 281 537 1 0 99 0
0 0 320416 3024932 198648 1074924 0 0 0 308 318 541 0 0 99 1
0 0 320416 3024932 198648 1074968 0 0 0 0 208 416 0 0 99 0
0 0 320416 3026800 198648 1072616 0 0 0 0 207 389 0 0 100 0

輸出結果可以歸爲這幾類:procs(進程)、memory(內存使用)、swap(內存頁面交換)、io(磁盤使用)、system(內核切換到內核代碼的次數)以及cpu(系統各組件使用CPU的時間)。

上例中的輸出結果是系統負載不大的一種典型情況。通常我們會從第二行看起,因爲第一行是系統整個運行時期的平均值。上例中,系統有320 416 KB內存被交換到磁盤(swpd),有大約3025000 KB(3 GB)空閒內存(free)。雖然有一部分交換空間正在被佔用,但是si(換入,swap-in)和so(換出,swap-out)列仍顯示內核沒有在磁盤交換內存。buff列顯示內核用於磁盤緩衝區的內存。

在最右邊的cpu列,你可以看到CPU時間被分爲us、sy、id和wa列。它們依次代表用戶任務、系統(內核)任務、空閒時間和I/O等待時間佔用的CPU時間的百分比

I/O監控

默認情況下,vmstat顯示常用的I/O統計信息

使用iostat

和vmstat類似,iostat在不帶任何參數時顯示系統當前的運行時間信息:

$ iostat
[kernel information]
avg-cpu: %user %nice %system %iowait %steal %idle
               4.46    0.01    0.67        0.31      0.00    94.55
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda      4.67  7.28         49.86       9493727 65011716
sde     0.00   0.00         0.00        1230        0

上面avg-cpu部分和本章介紹的其他工具一樣,顯示的是CPU的使用信息,往下是各個設備的情況

  • tps:平均每秒數據傳輸量
  • kB_read/s:平均每秒數據讀取量
  • kB/wrtn/s:平均每秒數據寫入量
  • kB/read:數據讀取總量
  • kB/wrtn:數據寫入總量

使用iotop查看進程的I/O使用和監控

使用方法和top一樣。它會持續顯示使用I/O最多的進程,最頂端是彙總數據

# iotop
Total DISK READ: 4.76 K/s | Total DISK WRITE: 333.31 K/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
260 be/3 root 0.00 B/s 38.09 K/s 0.00 % 6.98 % [jbd2/sda1-8]
2611 be/4 juser 4.76 K/s 10.32 K/s 0.00 % 0.21 % zeitgeist-daemon
2636 be/4 juser 0.00 B/s 84.12 K/s 0.00 % 0.20 % zeitgeist-fts
1329 be/4 juser 0.00 B/s 65.87 K/s 0.00 % 0.03 % soffice.b~ash-pipe=6
6845 be/4 juser 0.00 B/s 812.63 B/s 0.00 % 0.00 % chromium-browser
19069 be/4 juser 0.00 B/s 812.63 B/s 0.00 % 0.00 % rhythmbox

請注意,除了user、command、read、write列之外,還有一列叫TID(也就是線程ID),而非PID(即進程ID)。iotop是爲數不多的顯示線程而非進程的工具。

PRIO(意思是優先級)列表示I/O的優先級。它類似於我們介紹過的CPU優先級,但它還會決定內核爲進程調度I/O讀寫操作分配多長時間。

如果優先級爲be/4,則be代表調度等級,數字代表優先級別。和CPU優先級一樣,數字越小,優先級越高。比如內核會爲be/3的進程分配比be/4的進程更多的時間。

內核使用調度等級爲I/O調度施加更多的控制。iotop中有以下三種調度等級。

  • be:即best-effort(盡力)。內核盡最大努力爲其公平地調度I/O。大部分進程是在這類I/O調度等級下運行。
  • rt:即real-time(實時)。內核優先調度實時I/O。
  • idle:空閒。內核只在沒有其他I/O工作的時候安排此類I/O工作。該調度等級不具備優先級。

你可以使用ionice工具來查看和更改進程的I/O優先級

使用pidstat 監控進程

pidstat工具能夠讓你使用vmstat的方式來查看進程在過去某個時間段內的資源使用情況。

對進程1329監控結果,按秒記錄

$ pidstat -p 1329 1
Linux 3.2.0-44-generic-pae (duplex) 07/01/2015 _i686_ (4 CPU)
09:26:55 PM PID %usr %system %guest %CPU CPU Command
09:27:03 PM 1329 8.00 0.00 0.00 8.00 1 myprocess
09:27:04 PM 1329 0.00 0.00 0.00 0.00 3 myprocess
09:27:05 PM 1329 3.00 0.00 0.00 3.00 1 myprocess
09:27:06 PM 1329 8.00 0.00 0.00 8.00 3 myprocess
09:27:07 PM 1329 2.00 0.00 0.00 2.00 3 myprocess
09:27:08 PM 1329 6.00 0.00 0.00 6.00 2 myprocess

該命令在默認情況下顯示用戶時間和系統時間的百分比,以及綜合的CPU時間百分比,還顯示進程在哪一個CPU上運行。(%guest列有一點奇怪,指進程在虛擬機上運行時間的百分比。除非你是在運行虛擬機,否則可以忽略它。)

其他

資源監控和性能分析的更加深入的工具有以下幾方面

  • sar(即系統活動報告,System Activity Reporter):sar包含很多vmstat的持續監控功能,另外還記錄系統資源隨時間使用情況。sar讓你能夠查看過去某一時刻的系統狀態,這在你需要查看已發生的系統事件時非常有用。
  • acct(即進程統計):acct能夠記錄進程以及它們的資源使用情況。
  • Quotas(即配額):你可以將某些系統資源限制給某個進程或用戶使用。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章