1. 程式人生 > >《Linux性能及調優指南》----1.1 Linux進程管理

《Linux性能及調優指南》----1.1 Linux進程管理

內存 設計 order 輕量 地址空間 了解linux tro tar 完成

翻譯:飛哥 ( http://hi.baidu.com/imlidapeng )

版權所有,尊重他人勞動成果,轉載時請註明作者和原始出處及本聲明。

原文名稱:《Linux Performance and Tuning Guidelines》

原文地址:http://www.redbooks.ibm.com/abstracts/redp4285.html

-------------------------------------------------------------------------------------------

1.1.1 進程是什麽?
1.1.2 進程生命周期
1.1.3 線程
1.1.4 進程優先級和Nice值
1.1.5 上下文交換
1.1.6 中斷處理
1.1.7 進程狀態
1.1.8 進程內存段
1.1.9 CPU調度器

-------------------------------------------------------------------------------------------

進程管理對於任何一個操作系統來說都是最重要的任務之一。高效的進程管理能保證應用平穩有效的運行。linux的進程管理與UNIX十分相似。它包括進程調度、中斷處理、信號發送、進程優先級、進程切換、進程狀態、進程內存等。在本章節中,我將討論Linux進程管理的原理。它能幫助你更好的了解Linux內核是怎樣管理進程來影響系統性能的。

1.1.1 進程是什麽?


進程就是執行程序運行在處理器上的一個實例。進程可以使用Linux內核所能控制的任何資源來完成它的任務。所有運行在Linux操作系統上的進程都使用一個名叫task_struct的結構來管理,這個結構亦被稱作進程描述符【Process Descriptor】。進程描述符包括進程運行的所有信息如進程ID、進程屬性和構建這個進程所需要的資源。如果你清楚進程的結構,就能了解到什麽對於 進程執行和效能來說是重要的。圖1-2展現了進程結構的概要。


技術分享

圖 1-2 task_struct結構

1.1.2 進程生命周期

每個進程都有自己的生命周期如創建、執行、結束和消除。這些階段在系統啟動運行中會被重復無數次。因此從性能角度來看進程生命周期是極其重要的。圖1-3展示進程典型的生命周期


技術分享

圖1-3進程典型的生命周期

當進程創建一個新的進程,創建進程(父進程)發出fork()系統調用。當一個fork()系統調用被發出,它將得到一個關於新進程(子進程)的進 程描述符並設置一個新的進程ID。它會將父進程的進程描述符中所有數據復制到子進程。此時父進程的整個地址空間並沒有被復制的,所以父子進程會共享相同的 地址空間。exec()系統調用會復制一個新的程序到子進程的地址空間。因為父子進程共享相同的地址空間,所以當新程序寫入數據時會導致分頁錯誤【page fault】的例外發生。這時候內核會分配給子進程一個新的物理分頁。這個推遲的操作被叫做寫時復制

【Copy On Write】。子進程通常是執行自己的程序,與其父進程所執行的有所不同。這樣的操作可以避免沒有必要的系統開銷,因為復制整個地址空間是一個非常慢而且 效率低的操作,它會消耗很多處理器時間和資源。當程序執行完成時,子進程調用exit()系統調用結束。系統調用exit()會釋放進程的大部分數據結構並發送信號通知父進程。此時子進程被稱作僵 屍進程 【zombie process】。在子進程使用wait()系統調用讓父進程知道其已經結束之前,子進程是不會被清除的。當父進程得到子進程結束的通知後,會立即清除子進程的所有數 據結構並釋放進程描述符。

1.1.3 線程

線程是由一個單獨進程產生的執行單元。它與同一進程中的其他線程並行運行。它們能共享同一資源如內存、地址空間、打開的文件等。它們能訪問同樣一組 應用數據。線程也被稱作輕量級進程 (Light Weight Process LWP)。因為它們共享資源,線程不可以在同一時間修改它們共享的資源。互斥的實現、鎖、序列化等是用戶應用的職責。從性能角度來說,創建線程要比創建進程的開銷小,因為線程在創建時不需要復制資源。另一方面,進程和線程在調度算法方面上有很多相似的特性。內核在 處理它們時都使用類似的方法。


技術分享

圖1-4 進程和線程

在目前Linux的實現中,線程支持可移植操作系統接口(POSIX)。在Linux操作系統中有幾種線程的實現。下面列舉幾種最常使用的線程實 現。


? LinuxThreads

LinuxThreads自從Linux內核2.0就被作為默認的線程實現。但LinuxThread有許多實現與POSIX標準不兼容。 Native POSIX Thread Library(NPTL)正在取代LinuxThreads。在未來的Linux企業發行版中將不在支持LinuxThreads。


? Native POSIX Thread Libray(NPTL)本地POSIX線程庫

NPTL最初是由Red Hat開發。NPTL與POSIX標準更加兼容。利用2.6內核增強特性如新的系統調用clone()、信號處理實現等,它可以提供較 LinuxThreads更好的性能和伸縮性。

NPTL與LinuxThreads有很多的不兼容之處。一個應用如果依賴於LinuxThreads,可能在NPTL實現中無法工作。


? Next Generation POSIX Thread(NGPT)下一代POSIX線程

NGPT是IBM開發的POSIX線程庫的版本。目前處於維護階段,未來也沒有開發計劃。

使用LD_ASSUME_KERNEL環境變量,你可以設定應用使用哪個線程庫。


1.1.4 進程優先級和Nice值


進程優先級 【Process priority】是一個數值,用來讓CPU根據動態優先級和靜態優先級來決定進程執行的順序。一個高優先級的進程可以獲得更多在處理器上運行的機會。內核會根據進程的行為和特性使用試探算法【Heuristic Algorithm】來動態調高和調低動態優先級。用戶進程可以通過進程Nice 的 值間接改變靜態優先級。靜態優先級高的進程可以獲得較長的時間片【Time Slice】(進程能運行在處理器有多長時間)。

Linux中Nice值範圍為19(最低優先級)到-20(最高優先級),默認值為0。要將Nice值更改為負數,必須通過登錄或使用su命令由 root執行。


1.1.5 上下文交換【Context switching】


在進程執行過程中,進程信息存儲在處理器的寄存器和緩存中。這組為執行中進程而載入寄存器的數據被稱作上下文 【Context】。 為切換進程,當前執行中進程的上下文會被暫存,下一個執行進程的上下文會被還原到寄存器,進程描述符和內核模式堆棧【Kernel mode stack】的區塊會被用來存儲上下文,這個交換過程被叫做上下文交換【Context Switching】。發生過多的上下文交換是不好的,因為處理器每次都要刷新寄存器和緩存為新進程讓出資源,這會導致性能上的問題。圖1-5 說明了上下文交換是怎樣工作的。


技術分享

1.1.6 中斷處理


中斷處理是優先級最高的任務之一。中斷通常是由I/O設備產生的如網卡、鍵盤、硬盤控制器、串行適配器等。中斷控制會向內核發送一個事件通知(如鍵 盤輸入、以太幀到達等),它指示內核中斷執行中的進程並盡快處理中斷,因為大多數設備需要快速的回應,這對系統性能是很關鍵的。當一個中斷信號到達內核 時,內核必須切換當前執行的進程到處理中斷的新進程,這意味著中斷會觸發上下文交換,因此大量的中斷可以導致系統性能的下降。

在Linux中,有兩種類型的中斷。一種為硬中斷 【Hard Interrupt】,是由需要回應的設備產生的(硬盤I/O中斷、網絡適配器中斷,鍵盤中斷,鼠標中斷)。另一種為軟中斷 【Soft Interrupt】,用於可以延後執行的任務(TCP/IP操作,SCSI協議操作等)。你可以在/proc/interrupts 中 查看到有關硬中斷的信息。

在多處理器環境下,每個處理器都可以用來處理中斷。將中斷綁定到某一個物理處理可以提升系統的性能。要了解更詳細的內容,請參考4.4.2“關於中 斷處理的CPU親和力【CPU Affinity】”。


1.1.7 進程狀態


每個進程都有它自己的狀態,來顯示進程當前的情況。在進程執行過程中其狀態會發生變化。可能狀態有如下幾種:

? TASK_RUNNING【運行中】

此狀態表示進程正運行在CPU上或在隊列中等待運行(運行隊列【Run Queue】)。

? TASK_STOPPED【停止】

當進程接收到某些信號(例如SIGINT、SIGSTOP)後被暫停就處於此種狀態,該等待的進程在收到恢復信號如SIGCONT後會重新投入運 行。

? TASK_INTERRUPTIBLE【可中斷】

在這種狀態下,進程被暫停運行,等待某些狀態的達成。如果一個處於可中斷狀態的進程收到停止的信號,將變更進程的狀態並中斷操作。可中斷狀態進程的 一個典型例子就是等待鍵盤的輸入。

? TASK_UNINTERRUPTIBLE【不可中斷】

此狀態基本上與可中斷狀態十分相似。但可中斷狀態進程可以被中斷,而向一個不可中斷進程發送信號卻不會有任何反應。不可中斷狀態進程的一個典型例子 就是等待硬盤I/O操作。

? TASK_ZOMBIE【僵屍】

在進程使用系統調用exit() 退出後,其父進程就會知道。僵屍狀態的進程會等待父進程通知其釋放所有的數據結 構。


技術分享
圖1-6 進程狀態

僵屍進程

當一個進程收到信號並已經終止,它通常需要一些時間來完成結束前的所有任務(如關閉打開的文件)。在這個通常很短的時間裏,該進程就是一個僵 屍 (Zombie)。

當進程完成所有的關閉任務後,它會向父進程報告其即將終止。但有時僵屍進程並不能將自己終止,在這種情況狀態會顯示為(Zombie)。

使用kill命令是不可能結束這樣一個進程的,因為這個進程被認為已經死掉了。如果你不能清除僵屍,你可以結束其父進程,這樣僵屍也會隨之消失。然 而如果父進程是init進程,你就不可以結束它,因為init進程是一個極為重要的進程。因此你可能需要重新啟動系統來清除這個僵屍進程。


1.1.8 進程內存段


一個進程需要使用自己的內存區域來執行工作。工作的變化隨情況和進程用法而定。一個進程可以有不同的工作負載特性和不同的數據大小的需求,進程需要 處理數據的大小多種多樣。為了滿足這樣的需求,Linux內核使用動態內存分配機制。進程內存分配結構如圖1-7。


技術分享
圖1-7 進程地址空間

進程的內存區有幾部分組成

? 文字段

用來存儲執行代碼。

? 數據段

數據段由三塊區域組成。

― 數據【Data】:存儲已初始化數據如靜態變量。

― BSS :存儲零初始化的數據,數據被初始化為零。

― 堆【Heap】:這塊區域由malloc()用來按需要分配動態內存。堆向高地址擴張。

? 堆棧段

用來存儲本地變量、函數參數、函數返回地址。堆棧段向低地址擴張。

使用pmap 命令可以顯示用戶進程地址空間的內存分配。你可以使用ps 命令 顯示此內存段的大小。參考2.3.10“pmap”和2.3.4“ps和pstree”。


1.1.9 Linux CPU調度器


計算機的基本功能非常簡單就是計算。為了計算,這就意味要管理計算資源或處理器和計算任務(被稱作線程或進程)。Linux內核使用與過去CPU調 度器使用的算法O(n)截然不同的O(1)算法,這要感謝Lngo Molnar的巨大貢獻。O(1)指的是一種靜態算法,意思就是不管進程的數量有多少,進程的執行時間都是不變的。

這種新的調度器的擴展性非常好,不管進程的數量或處理器的數量有多少,系統的開銷都是非常小的。此算法中使用到兩個進程優先級數組:

? 活動的【Active】

? 過期的【Expired】

調度器根據進程的優先級和優先攔截率【Prior Blocking Rate】分配時間片,然後它們被以優先級順序置於活動數組【Active Array】中。當時間片耗盡,它們會被分配一個新的時間片並置於過期數組中。當活動數組中所有進程的時間片都全部耗盡,兩個數組會被互換並重新執行。對 於交互進程(相對於實時進程),擁有長時間片的高優先級進程可以得到比低優先級進程更多的時間,但這並不意味著低優先級的進程會被置之不理。在企業環境 中,擁有很多的處理器並經常出現大量的線程和進程,這樣做可以大大提升Linux內核的伸縮性。新的O(1)CPU調度器被設計用於2.6內核,但已被移 植到2.4內核家族。圖1-8說明了Linux CPU調度器是怎樣工作的。


技術分享
圖1-8 Linux 2.6內核 O(1)調度器

新調度器另一個大的改進就是支持非一致性內存架構(NUMA)和對稱多線程處理器,如Intel超線程技術。改良後的NUMA支持確保只有當某個節點過載時,負載平衡才會跨越NUMA節點。This mechanism ensures that traffic over the comparatively slow scalability links in a NUMA system are minimized。盡管在每個調度節拍【tick】時負載平衡會遍歷調度域群組【Scheduler Domain Group】中的處理器,但只有在節點過載並請求負載平衡時,負載才會跨越調度域【Scheduler Domain】轉移。


技術分享
圖1-9 O(1) CPU調度器結構

譯者註:在翻譯過程中,深深的感覺到進程調度是一項非常復雜的工作。如果想深入了解2.6內核進程調度還需要多多查看相關資料,下面是一些 關於2.6內核進程調度的文章,有興趣的朋友不妨看看。

Linux 2.6 調度系統分析:http://www.ibm.com/developerworks/cn/linux/kernel/l-kn26sch/index.html
Linux 的 NUMA 技術:http://www.ibm.com/developerworks/cn/linux/l-numa/index.html
Linux Scheduling Domains:http://www.ibm.com/developerworks/cn/linux/l-cn-schldom/index.html
Inside the Linux scheduler:http://www.ibm.com/developerworks/linux/library/l-scheduler/

《Linux性能及調優指南》----1.1 Linux進程管理