實驗總結分析報告 ——從系統的角度分析影響程式執行效能的因素

sally發表於2021-05-13

實驗總結分析報告

——從系統的角度分析影響程式執行效能的因素

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的知識!

相關文章