Linux實驗總結(jié)分析報告:從系統(tǒng)的角度分析影響程序執(zhí)行性能的因素
前言
感謝孟老師和李老師在這門課中對我的教導,讓我受益匪淺,對Linux內(nèi)核基本結(jié)構(gòu)和工作原理有了更深層次的認識,
學到了很多,再次感謝兩位老師。
一、精簡的Linux系統(tǒng)的概念模型
馮·諾依曼體系結(jié)構(gòu)如圖所示,其中運算器、存儲器、控制器、輸入設(shè)備和輸出設(shè)備5大基本類型部件組成了計算機硬件;
核心是CPU,與內(nèi)存和輸入輸出(I/O)設(shè)備進行交互,是整個計算機的靈魂、大腦。內(nèi)存則是存放了指令和數(shù)據(jù),二者
皆以二進制形式存放。輸入輸出設(shè)備則包括鼠標、鍵盤、顯示器與磁盤等等設(shè)備,是計算機與外界進行交互的工具。

二、計算機的“三大法寶”和操作系統(tǒng)的“兩把寶劍”
- 三大法寶
-
存儲程序:指令和數(shù)據(jù)以二進制形式存儲在內(nèi)存中
-
堆棧:函數(shù)調(diào)用是基于堆棧實現(xiàn)的,棧在程序運行中具有舉足輕重的地位。棧保存了一個函數(shù)調(diào)用所需要的維護信息,被稱之為堆棧幀或活動記錄
-
中斷:是實現(xiàn)程序并發(fā)執(zhí)行的基礎(chǔ)
-
- 兩把寶劍
-
中斷上下文:硬件通過中斷觸發(fā)信號,導致內(nèi)核調(diào)用中斷處理程序,進入內(nèi)核空間。這個過程中,硬件的一些變量和參數(shù)也要傳遞給內(nèi)核,內(nèi)核通過這些參數(shù)進行中斷處理。中斷上文可以看作就是硬件傳遞過來的這些參數(shù)和內(nèi)核需要保存的一些其他環(huán)境(主要是當前被中斷的進程環(huán)境。
-
進程上下文:其是指進程由用戶態(tài)切換到內(nèi)核態(tài)是需要保存用戶態(tài)時cpu寄存器中的值,進程狀態(tài)以及堆棧上的內(nèi)容,即保存當前進程的進程上下文,以便再次執(zhí)行該進程時,能夠恢復(fù)切換時的狀態(tài),繼續(xù)執(zhí)行。
-
三、Linux內(nèi)核
-
Linux內(nèi)核體系結(jié)構(gòu)
![]()
-
簡析
最上面是用戶(或應(yīng)用程序)空間。這是用戶應(yīng)用程序執(zhí)行的地方。用戶空間之下是內(nèi)核空間,Linux 內(nèi)核正是位于這里。GNU C Library (glibc)也在這里。它提供了連接內(nèi)核的系統(tǒng)調(diào)用接口,還提供了在用戶空間應(yīng)用程序和內(nèi)核之間進行轉(zhuǎn)換的機制。這點非常重要,因為內(nèi)核和用戶空間的應(yīng)用程序使用的是不同的保護地址空間。每個用戶空間的進程都使用自己的虛擬地址空間,而內(nèi)核則占用單獨的地址空間。
Linux 內(nèi)核可以進一步劃分成 3 層。最上面是系統(tǒng)調(diào)用接口,它實現(xiàn)了一些基本的功能,例如 read 和 write。系統(tǒng)調(diào)用接口之下是內(nèi)核代碼,可以更精確地定義為獨立于體系結(jié)構(gòu)的內(nèi)核代碼。這些代碼是 Linux 所支持的所有處理器體系結(jié)構(gòu)所通用的。在這些代碼之下是依賴于體系結(jié)構(gòu)的代碼,構(gòu)成了通常稱為 BSP(Board Support Package)的部分。這些代碼用作給定體系結(jié)構(gòu)的處理器和特定于平臺的代碼。
四、進程管理

進程狀態(tài)轉(zhuǎn)換圖
進程管理的重點是進程的執(zhí)行。在內(nèi)核中,這些進程稱為線程,代表了單獨的處理器虛擬化(線程代碼、數(shù)據(jù)、堆棧和 CPU 寄存器)。在用戶空間,通常使用進程 這個術(shù)語,不過 Linux 實現(xiàn)并沒有區(qū)分這兩個概念(進程和線程)。內(nèi)核通過 SCI 提供了一個應(yīng)用程序編程接口(API)來創(chuàng)建一個新進程(fork、exec 或 Portable Operating System Interface [POSIX] 函數(shù)),停止進程(kill、exit),并在它們之間進行通信和同步(signal 或者 POSIX 機制)。
進程管理還包括處理活動進程之間共享 CPU 的需求。內(nèi)核實現(xiàn)了一種新型的調(diào)度算法,不管有多少個線程在競爭 CPU,這種算法都可以在固定時間內(nèi)進行操作。這種算法就稱為 O(1) 調(diào)度程序,這個名字就表示它調(diào)度多個線程所使用的時間和調(diào)度一個線程所使用的時間是相同的。O(1) 調(diào)度程序也可以支持多處理器(稱為對稱多處理器或 SMP)。您可以在 ./linux/kernel 中找到進程管理的源代碼,在 ./linux/arch 中可以找到依賴于體系結(jié)構(gòu)的源代碼。
五、中斷和異常
中斷何和異常是指明系統(tǒng)、處理器或當前執(zhí)行程序(或任務(wù))的某處出現(xiàn)一個事件,該事件需要處理器進行處理。通常,這種事情會導致執(zhí)行控制器被強迫從當前運行程序轉(zhuǎn)移到被稱為終端處理程序或異常處理程序的特殊軟件函數(shù)或任務(wù)中。處理器響應(yīng)中斷或異常所采取的行動稱為中斷/異常服務(wù)(處理)。
通常中斷發(fā)生在程序執(zhí)行的隨機時刻,以響應(yīng)硬件發(fā)出的信號。系統(tǒng)硬件使用中斷來處理外部事件,例如要求為外部設(shè)備提供服務(wù)。當然,軟件也能通過執(zhí)行 INT n 指令產(chǎn)生中斷。
異常發(fā)生在處理器執(zhí)行一條指令時,檢測到一個出錯條件時發(fā)生,例如被0除出錯條件。處理器可以檢測到各種出錯條件,包括違反保護機制。頁錯誤以及機器內(nèi)部錯誤。對應(yīng)用程序來說,80x86的中斷和異常處理機制可以透明地處理發(fā)生的異常和中斷事件。當收到一個中斷或檢測到一個異常時,處理器會自動把當前正在正在執(zhí)行的程序或任務(wù)掛起,并開始運行中斷或異常處理程序。當處理程序執(zhí)行完畢,處理器就會恢復(fù)并繼續(xù)執(zhí)行被中斷的程序或任務(wù)。被中斷程序的恢復(fù)過程并不會失去程序執(zhí)行的連貫性,除非從異常中恢復(fù)是不可能的或者中斷異常導致當前運行程序被終止。
六、內(nèi)存管理
內(nèi)核所管理的另外一個重要資源是內(nèi)存。為了提高效率,如果由硬件管理虛擬內(nèi)存,內(nèi)存是按照所謂的內(nèi)存頁 方式進行管理的(對于大部分體系結(jié)構(gòu)來說都是 4KB)。Linux 包括了管理可用內(nèi)存的方式,以及物理和虛擬映射所使用的硬件機制。不過內(nèi)存管理要管理的可不止 4KB 緩沖區(qū)。Linux 提供了對 4KB 緩沖區(qū)的抽象,例如 slab 分配器。這種內(nèi)存管理模式使用 4KB 緩沖區(qū)為基數(shù),然后從中分配結(jié)構(gòu),并跟蹤內(nèi)存頁使用情況,比如哪些內(nèi)存頁是滿的,哪些頁面沒有完全使用,哪些頁面為空。這樣就允許該模式根據(jù)系統(tǒng)需要來動態(tài)調(diào)整內(nèi)存使用。為了支持多個用戶使用內(nèi)存,有時會出現(xiàn)可用內(nèi)存被消耗光的情況。由于這個原因,頁面可以移出內(nèi)存并放入磁盤中。這個過程稱為交換,因為頁面會被從內(nèi)存交換到硬盤上。內(nèi)存管理的源代碼可以在 ./linux/mm 中找到。
七、虛擬文件系統(tǒng)
虛擬文件系統(tǒng)(VFS)是 Linux 內(nèi)核中非常有用的一個方面,因為它為文件系統(tǒng)提供了一個通用的接口抽象。VFS 在 SCI 和內(nèi)核所支持的文件系統(tǒng)之間提供了一個交換層

在 VFS 上面,是對諸如 open、close、read 和 write 之類的函數(shù)的一個通用 API 抽象。在 VFS 下面是文件系統(tǒng)抽象,它定義了上層函數(shù)的實現(xiàn)方式。它們是給定文件系統(tǒng)(超過 50 個)的插件。文件系統(tǒng)的源代碼可以在 ./linux/fs 中找到。文件系統(tǒng)層之下是緩沖區(qū)緩存,它為文件系統(tǒng)層提供了一個通用函數(shù)集(與具體文件系統(tǒng)無關(guān))。這個緩存層通過將數(shù)據(jù)保留一段時間(或者隨即預(yù)先讀取數(shù)據(jù)以便在需要是就可用)優(yōu)化了對物理設(shè)備的訪問。緩沖區(qū)緩存之下是設(shè)備驅(qū)動程序,它實現(xiàn)了特定物理設(shè)備的接口。
八、影響程序執(zhí)行性能的因素
- 源代碼因素
源代碼因素主要指必須通過修改代碼才可以解決或者緩解的問題。
- 全局變量初始化。這一部分在main函數(shù)之前完成,程序的全局變量或者其構(gòu)造函數(shù)過多會占用大量的CPU時間。
- 代碼自身消耗CPU。代碼低效,或者IO問題,可以通過定位之后加以優(yōu)化。
- 無用代碼呆滯可執(zhí)行文件過大,增加加載負荷。
- 動態(tài)鏈接庫因素
系統(tǒng)加載一個動態(tài)鏈接庫需要一個固定的時間消耗,所以庫的數(shù)量越大,占用的這部分時間就越多;
系統(tǒng)的IO以頁為單位,庫的大小越大,從庫總載入有效代碼的準確性就越低,導致IO操作的幾率就越高,占用的時間也越多;
啟動過程的動態(tài)鏈接庫個數(shù)越少越好,大小越小越好。
- 代碼調(diào)用引發(fā)缺頁導致IO。動態(tài)庫函數(shù)按照物理順序排列,而分散的調(diào)用將導致缺頁從而引起IO操作。
- 動態(tài)鏈接庫符號的可見性。動態(tài)鏈接庫導出過多的課件符號,加載器在匹配時將消耗過多的IO/CPU。
- 配置文件/資源文件因素
啟動部分的代碼頻繁訪問配置文件/資源文件從而導致IO過多,或者不同時間分次訪問這些文件從而導致IO操作分散而不能有效利用硬盤的連續(xù)訪問,導致性能下降。

浙公網(wǎng)安備 33010602011771號