實驗總結分析報告 ——從系統的角度分析影響程式執行性能的因素
實驗總結分析報告
——從系統的角度分析影響程式執行性能的因素
1、請您根據本課程所學內容總結梳理出一個精簡的Linux系統概念模型,最大程度統攝整頓本課程及相關的知識資訊,模型應該是邏輯上可以運轉的、自洽的,並舉例某一兩個具體例子(比如讀寫文件、分配記憶體、使用I/O驅動某個硬體等)納入模型中驗證模型。
2、然後將一個應用程式放入該系統模型中系統性的梳理影響應用程式性能表現的因素,並說明原因。
一、精簡的Linux系統概念模型
Linux系統概念模型可以分為四部分:內核,shell,系統調用,用戶程式。
(一)Linux內核
Linux內核,主要有以下幾個功能模組:中斷管理,時鐘管理,進程管理、記憶體管理、文件系統等
1.中斷管理
(1)中斷概念
簡而言之,中斷就是CPU把當前的任務先放一放,然後去執行其他任務,完成後再返回執行原來的任務。
(2)中斷類型
1. 外部中斷:外設引起的中斷
2. 內中斷:也稱為異常,可分為陷入和故障。
2.時鐘管理
x86體系的Linux中,主要用到了三種時鐘:實時時鐘RTC、時間戳計數器TSC及可編程間隔定時器PIT。其主要作用是:
1. 記錄系統時間。很多應用程式需要知道日期和時間、由日期和時間構成的時間戳也會被打在文件上面、等等;
2. 統計功能。如top之類的用戶程式可以查看一段時間內的系統負載、以及各個進程佔用CPU的時間、等等;
3. 定時功能。很多用戶程式會使用到定時器,比如sleep一段時間後做某件事情、比如給select設置一個超時時間、等等;
3.進程管理
(1)進程的概念
簡而言之,進程就是程式執行的過程。數據結構struct task_struct是描述進程的,保存了程式執行過程中的一些必要資訊,如進程的id,進程的狀態,堆棧等。
(2)進程的創建
⽗進程通過fork系統調⽤進⼊內核 do_fork函數,複製進程描述符及相關進程資源(采⽤寫時複製技術)、分配⼦進程的內核堆棧並對內核堆棧和thread等進程關鍵上下⽂進⾏初始化,最後將⼦進程 放⼊就緒隊列,fork系統調⽤返回;
⽽⼦進程則在被調度執⾏時根據設置的內核堆棧和thread等進程關鍵上下⽂開始執⾏。
(3)進程切換
1. 切換⻚全局⽬錄(CR3)以安裝⼀個新的地址空間,這樣不同進程的虛擬地 址如0x8048400(32位x86)就會經過不同的⻚錶轉換為不同的物理地址。
2. 切換內核態堆棧和進程的CPU上下⽂,因為進程的CPU上下⽂提供了內核執 ⾏新進程所需要的所有資訊,包含所有CPU暫存器狀態。
(4)進程調度
進程調度的時機:
1. 進程狀態發生變化時。
2. 當前進程時間片用完。
3. 進程從系統調用返回到用戶態。
4. 中斷處理後,進程返回到用戶態。
4.記憶體管理
Linux把進程地址空間分成內核區和用戶區兩部分。
當在內核態申請記憶體時直接給分配,而進程在用戶態申請記憶體時,只是給了一個新的線性地址空間的一個使用權,真的要用的時候會產生缺頁異常,然後再真的分配。
請求調頁是一種動態記憶體分配技術,它把頁框的分配推遲到不能再推遲為止。
與之相關的分配頁框的方式為寫時複製:父子進程是共享頁框的,當讀的時候,不分配新的頁框。當寫的時候,誰寫就給誰分配,兩者各自過運行一段時間都就都有了自己的空間。
5.文件系統
```text
Linux採用了虛擬文件系統(VFS)的形式,實現「一切皆文件」。
向上,對應用層 (的System Call) 提供一個標準的文件操作介面 (如read/write);
對下,對文件系統提供一個標準的介面,兼容多種文件系統可以方便的移植到Linux上;
當進程要讀某個文件時,進行系統調用read,產生一個中斷INT80,對應第120個中斷向量,找到中斷處理程式,帶上系統調用號。訪問文件系統中的文件。
```
6.Linux內核的啟動過程
1. 啟動引導載入程式BootLoader
2. 由BootLoader引導啟動內核kernel
3. 由kernel檢查和初始化硬體設備,載入設備的驅動程式模組,安裝root文件系統
4. kernel啟動一個名為init的進程,在init進程運行完成並啟動其他必要的後續進程後,系統開始運行,引導進程結束
(二)shell
1.概念
1. shell是作業系統的最外層,shell可以合併程式語言以控制進程和文件,以及啟動和控制其他程式。
2. 簡單來說:shell就是一個用戶跟作業系統之間交互的命令解釋器。
3. Linux常用的shell解釋器:/bin/bash
2.常見操作命令
1. 目錄相關的:ls, cd, mkdir, cp等
2. 查看文件相關的:find, cat, head, tail, more, less, vim, awk等
3. 其他:ifconfig, iptables, netstat, snap等
(三)系統調用
1.概念
Linux系統總體上可以劃分為內核態和用戶態,也可以說是內核和應用程式,系統調用就是提供給用戶程式的一組可以訪問內核的介面。
2.過程
1. 程式調用libc庫的封裝函數。
2. 調用軟中斷int 0x80進入內核。
3. 在內核中首先執行system_call函數(首先將系統調用號(eax)和可以用到的所有CPU暫存器保存到相應的堆棧中(由SAVE_ALL完成),接著根據系統調用號在系統調用表中查找到對應的系統調用服務常式。
4. 執行該服務常式。
5. 執行完畢後,轉入ret_from_sys_call 常式,從系統調用返回
(四)用戶程式
1.概念
用戶程式就是面向用戶的一些程式,最簡單的比如用C語言編寫的`HelloWorld.c`程式,複雜的比如系統中的瀏覽器等。
2.可執行程式的工作原理
1. 源程式碼是如何變成可執行文件的
(1)預編譯:處理源程式碼中的偽指令和一些特殊字元,並對一些相關的程式碼進行替換
(2)編譯:檢查語法並對程式碼進行優化,將文本文件 .i 翻譯成 .s 文件,得到彙編語言程式。
(3)彙編:將 .s 文件轉換成機器語言指令也就是二進位程式碼,並將結果保存在目標文件 .o 中
(4)鏈接:將所有的目標文件鏈接到一起形成可執行文件,分為動態鏈接和靜態鏈接。
2. 可執行文件是如何變成進程的
(1)調用execve載入可執行程式
(2)調用execve陷入內核
(3)系統調用execve返回用戶態
(4)被execve載入的可執行程式
二、一個實例——open函數
open的執行過程
1. open執行去C庫裡面,找到Int80 05指令封裝。80為中斷向量號,05為系統調用號
2. 從idtr暫存器中讀取中斷向量表的基地址,找到IDT。
3. trap-init調用set_system_gate等函數對中斷向量表中的每一項進行初始化,並將指令所在地址的cs、eip、DPL以及門類型和中斷向量號進行綁定。
4. 根據中斷向量號128找到第128項,其中包括cs和eip,再根據gdtr、cd、eip找到所要執行指令的地址,再進行系統調用。
5. 進入系統調用,保存現場,對指令進行分析得到系統調用號05根據系統調用號,找到系統調用表中的sysopen的入口,即sysopen的函數指針。
6. sysopen對文件進行查找,得到文件控制塊和文件類型。
7. 根據文件類型調用相應系統的文件打開函數,並在系統文件打開表中創建一個file,根據文件控制塊向其中填充file_operation以及偏移量等項
8. 返回到進程,進入進程文件打開表,其中有一個fd數組,將fd數組未使用的最低索引指向系統文件打開表中的相應項,然後將fd數組的下標返回給open。
三、影響程式執行性能的因素
1.CPU
CPU 是作業系統穩定運行的根本,CPU 的速度與性能很大一部分決定了系統整體的性能,因此 CPU 數量越多、主頻越高,伺服器性能也就相對越好。
但事實也並非完全如此,目前大部分 CPU 在同一時間內只能運行一個執行緒,超執行緒的處理器可以在同一時間運行多個執行緒,因而可以利用處理器的超執行緒特性提髙系統性能。
可以使用top, uptime, vmstat
等工具查看分析CPU,負載等情況。
2.記憶體
記憶體太小,系統進程將被阻塞,應用也將變得緩慢,甚至失去響應;記憶體太大,會導致資源浪費。
Linux 系統採用了物理記憶體和虛擬記憶體的概念,虛擬記憶體雖然可以緩解物理記憶體的不足,但是佔用過多的虛擬記憶體,應用程式的性能將明顯下降。要保證應用程式的高性能運行,物理記憶體一定要足夠大,但不應過大,否則會造成記憶體資源的浪費。
可以使用free, vmstat
等工具查看分析記憶體佔用情況。
3.磁碟I/O
在一個需要頻繁讀寫的應用中,如果磁碟 I/O 性能得不到滿足,就會導致應用的停滯。
不過,好在現今的磁碟都採用了很多方法來提高 I/O 性能,比如常見的磁碟 RAID 技術。
可以使用fdisk, iostat
等工具查看分析磁碟使用情況。
4.網路頻寬
低速的、不穩定的網路將導致網路應用程式的訪問阻塞;而穩定、高速的頻寬,可以保證應用程式在網路上暢通無阻地運行。
可以使用ping, netstat
等工具查看分析網路性能
5.應用程式本身
如果應用程式本身時間複雜度、空間複雜度等太高,會直接影響程式執行的性能。另外,應用程式使用的程式語言也會影響程式執行的性能,比如python、Java等,通常情況下程式性能是不如C/C++程式語言的。
四、總結
1. Linux精簡模型
內核、shell、系統調用、用戶程式
2. 影響應用程式性能的因素
CPU,記憶體、磁碟I/O,網路頻寬、應用程式本身
五、致謝
非常感謝李老師和孟老師的辛勤教學與指導,使我學到很多Linux的知識!