(1)Linux性能調優之Linux進程管理

1、背景

玩過一段時間Linux後,你們是否發現Linux也就是一個操做系統而已,和windows是相似的,只不過是windows擁有圖形化界面,而Linux大部分狀況下只是個黑黑的窗口。windows多用於我的,而Linux由於出色的性能而多用於服務器。算法

服務器不是智能的,Linux也不是智能的,因此須要運維人員經過調試,將服務器的硬件和Linux的特性結合起來,從而達到性能最大輸出,這就是我理解的Linux性能調優。下面展現的是一張服務器和Linux系統結合的概覽圖:windows

服務器和Linux系統結合的概覽圖

2、基礎知識

調優不是說調就調的,咱們要先了解Linux是如何處理任務以及與硬件資源進行交互的。性能調優須要在深入理解硬件資源、操做系統和應用程序的基礎上進行。下面說一下在Linux中和性能關係最密切的幾個部分。數組

3、Linux進程管理

  • 3.1 什麼是進程?

進程是在處理器中執行的實例,Linux內核調度各種資源來知足進程的需求。個人理解是,應用程序是存儲硬盤上的數據,經過程序入口將應用程序裝載到內存運行起來後就生成了一個進程(運行中的程序)。進程會使用各類資源,如CPU,鍵盤鼠標,處理器,硬盤等,而這些工做由Linux內核調度,以知足各個進程間的協同,競爭等。緩存

Linux的進程管理方式相似於Unix的進程管理方式,包含進程調度、中斷處理、信號、進程優先級、進程切換、進程狀態、進程的內存等等bash

全部運行在Linux操做系統的進程都被task_struct這個結構體管理,task_struct也被稱爲進程描述符。進程描述符包含一個進程運行所需的全部信息,好比進程的id、進程的屬性以及構建進程的資源。服務器

下圖展現了進程信息相關結構的概覽:網絡

  • 3.2 進程的生命週期

每一個進程都有本身生命週期,好比建立、執行、終止和刪除。在系統運行過程當中,這些階段反覆執行成千上萬次。所以,從性能的角度來看,進程的生命週期十分重要。數據結構

下圖展現了通常進程的生命週期:多線程

當一個進程建立一個新的進程,建立進程的進程(父進程)使用名爲fork()的系統調用。當fork()被調用的時候,它會爲新建立的進程(子進程)得到一個進程描述符,而且設置新的進程ID。複製父進程的進程描述符給子進程。這時候,不會複製父進程的地址空間,而是父子進程使用一樣的地址空間。架構

exec()系統調用把新程序複製到子進程的地址空間。因爲共享一樣的地址空間,寫入新進程的數據會引起頁錯誤的異常。此時,內核給子進程分配新的物理頁。這個延遲的操做叫作Copy On Write。子進程和父進程執行的程序一般不同,它執行本身的程序。這個操做避免了沒必要要的開銷,由於,複製整個地址空間是很慢且低效率的,還會消耗不少的處理器時間和資源。

當程序執行完成,子進程使用exit()系統調用終止。exit()會釋放進程的大部分數據結構,而且把這個終止的消息通知給父進程。這時候,子進程被稱爲zombie process(殭屍進程)。直到父進程經過wait()系統調用知悉子進程終止以前,子進程都不會被徹底的清除。一旦父進程知道子進程終止,它會清除子進程的全部數據結構和進程描述符。

  • 3.3 線程

說到進程不得不提的就是線程了。線程是單個進程中生成的執行單元。多個線程在同一個進程中併發運行。它們共享內存、地址空間、打開文件等等資源。還能訪問一樣的應用數據集。線程也被稱爲輕量級進程(Light Weight Process)。因爲線程間共享資源,線程不能同時改變它們共享的資源。互斥、鎖、序列化等等都是由用戶應用程序來實現。

從性能的角度看,建立線程比建立進程更加低消耗,由於建立線程不須要複製資源。另外一方面,從進程和線程在調度上看,他們擁有類似的行爲。內核用相似的方法來處理他們。

下圖是進程和線程的簡單對比:

在當前的Linux實現中,線程由POSIX(Portable Operating System Interface for UNIX,可移 植操做系統接口)的兼容庫(pthread)提供。Linux支持多線程。

  • 3.4 進程優先級和nice級別

進程優先級由動態優先級和靜態優先級決定,它是決定進程在CPU中執行順序的數字。優先級越高的進程被處理器執行的機會越大。

根據進程的行爲,內核使用啓發式算法決定開啓或關閉動態優先級。能夠經過nice級別直接修改進程的靜態優先級,擁有越高靜態優先級的進程會得到更長的時間片(時間片是進程在處理器中的執行時間)。

Linux支持的nice級別從19(最低優先級)到-20(最高優先級),默認只是0。只有root身份的用戶才能把進程的nice級別調整爲負數(讓其具有較高優先級)。

  • 3.5 切換上下文

在進程執行過程當中,進程的信息存放在處理器的寄存器和緩存中。這部分執行中進程存放在寄存器中的數據就叫作context,上下文。在切換進程中,正在處理的進程上下文被保存起來,把下一個要執行的進程的上下文恢復到寄存器。上下文一般存儲在進程描述符和內核態棧中。進程切換就叫作上下文切換(context switching)。由於處理器每次上下文切換都要爲新進程刷新寄存器和緩存,可能引起性能上的問題,因此應該儘可能避免太多的上下文切換。 下圖描述上下文切換是如何工做的:

  • 3.6 中斷處理

中斷處理是最高優先級別的任務之一。中斷一般由I/O設備產生,譬如網絡接口、鍵盤、磁盤控制器。中斷處理器把鍵盤輸入、網絡幀到達這類事件通知給內核,它告訴內核儘快中斷進程執行,由於某些設備須要快速的迴應。這對系統穩定性是一個挑戰。當中斷信號到達內核,內核必須切換當前執行中的進程到新的進程,處理中斷。這就意味着會發生上下文切換,同時也意味着大量的的中斷會致使系統性能降低。

在Linux中有兩類中斷,硬中斷是由設備產生的須要作出響應的中斷,例如磁盤I/O中斷,網卡中斷,鍵盤和鼠標中斷。軟中斷用於任務處理,能夠推遲,例如TCP/IP操做、SCSI協議操做。能夠在/proc/interrupts中看到相關的硬中斷信息。

  • 3.7 進程狀態

TASK_RUNNING 在這個狀態中,進程正在CPU中執行,或者在運行隊列(run queue)中等待運行。

TASK_STOPPED 進程因爲特定的信號(如SIGINT、SIGSTOP)而掛起就會處於這個狀態,等待恢復信號,好比SINCONT。

TASK_INTERRUPTIBLE 在此狀態中,進程掛起而且等待一個特定的條件。假如進程處於TASK_INTERRUPTIBLE狀態而且收到一箇中止信號,進程狀態會發生改變,操做會中斷。TASK_INTERRUPTIBLE的典型例子是等待鍵盤中斷。

TASK_UNINTERRUPTIBLE 相似於TASK_INTERRUPTIBLE。當進程處於TASK_INTERRUPTIBLE狀態能夠被中斷,發送一個信號給TASK_UNINTERRUPTIBLE卻不會有任何反應。TASK_UNINTERRUPTIBLE最典型的例子是進程等待磁盤I/O操做。

TASK_ZOMBIE 進程在使用exit()系統調用退出之後,父進程應該知道進程終結。在TASK_ZOMBIE狀態中,進程在等待父進程收到通知並釋放全部的數據結構。

它們之間的關係以下圖:

說下殭屍進程

當進程已經收到信號而終止,正常狀況下,徹底結束以前,它有一些時間來完成全部的任務(例如關閉打開的文件)。在這個很短的的正常的時間片裏,這個進程是殭屍。

當進程完成了全部的關閉操做, 它向父進程報告它即將終結。有時候,殭屍進程不可以結束它本身,這個狀態下,它就顯示狀態爲Z(zombie)。

由於它已經死了,因此不可能使用kill命令殺死這種進程。若是沒法擺脫殭屍進程,能夠殺死殭屍進程的父進程,這樣殭屍進程也會消失。而後,若是殭屍進程的父進程是init,你就別這麼作了,init是很是重要的進程,你可能要重啓才能擺脫殭屍進程了。

  • 3.8 進程內存段

進程使用本身的內存區域處理任務,任務種類由場景和進程用途決定。進程有不一樣的工做特性和不一樣數據大小要求,進程必須處理各類大小的數據。爲知足這一要求,Linux內核給各個進程使用動態內存分配機制。進程內存分配結構以下圖:

進程內存區域包含以下段:

文本 :存儲可執行代碼的區域
數據 : 數據段由以下三個區域構成
    Data:存儲初始化數據,好比靜態變量
    BSS:存儲初始化0數據,數據初始化爲0
    Heap(堆):根據須要使用malloc()分配動態內存。堆向高地址空間增加。
棧: 該區域存儲局部變量、函數參數和函數的返回地址。棧向低地址空間增加。
複製代碼

用戶進程的地址空間分配可使用pmap命令顯示出來。你可使用ps命令顯示總的段大小。

  • 3.9 Linux的CPU調度

計算機的最基本功能就是計算,爲了實現計算功能,必需要有辦法管理計算資源、處理器、計算任務,也就是常說的進程和線程。

下面談下Linux中CPU調用進程的算法,這個算法使用兩個進程優先級數組:

1.active
2.expired
複製代碼

因爲調度器根據進程的優先級和先前阻塞率來位分配時間片,進程的優先級被放在一個active數組中。當時間片到期,它們被從新分配新的時間片,而且放置到expired數組上。當全部active數組上的進程都到期,active和expired數組發生對換,重啓算法。對於通常的交互進程(對應實時進程),高優先級的進程一般會比低優先級進程分配更多的時間片,可是並不意味着徹底不給低優先級進程機會。

以下展現和Linux的CPU調度器是如何工做的:

新調度器的另一個大有有點是支持非均勻內存架構(Non-Uniform Memory Architecture, NUMA)和對稱多線程處理器,例如Intel的超線程技術。支持NUMA保證了正常狀況下不會出現負載均衡的狀況,除非一個節點負擔太重。這個機制保證了在NUMA系統中,比較緩慢的鏈路負載較小。儘管在一個組中的處理器調度的每個處理,會被負載均衡,可是調度器的組只會在節點負載太高和要求負載均衡的時候產生。

4、下一節是???

談完Linux的進程管理,下一節談一下 Linux的內存體系

相關文章
相關標籤/搜索