目錄1.2 記憶體管理
1.3 檔案管理
1.4 驅動裝置程式
1.5 具體例子
2. 影響應用程式效能表現的因素
作業系統按照功能可以劃分為程序管理、記憶體管理、檔案管理以及裝置管理,而linux核心也對此進行了實現
程序管理可以說是作業系統核心中最為核心的部分,其主要完成的一些功能可以概述為如下幾點:
描述程序
程序的排程切換
程序間通訊
在linux核心中,採用task_struct
資料結構(即程序控制塊pcb)來描述乙個程序,task_struct
結構體所包含的內容異常複雜,包括了程序的狀態state
、用於程序管理的程序鍊錶tasks
、描述檔案系統和程序開啟檔案的檔案描述幅fs
和files
以及相應的記憶體管理mm
等成員變數。
由上所述可以看出,通過程序描述符可以將linux下的程序排程、通訊、記憶體管理、檔案系統、以及驅動裝置管理等模組進行良好的串聯。
linux系統屬於乙個多工的作業系統,因此一般在同一時間段內不可能只執行乙個程序,大多數情況下是存在多程序併發執行的。因此為了合理的安排各程序占用cpu的時間以及等待cpu的時間,便引出了程序排程切換的問題。
在linux下,程序排程策略主要可分為先進先出策略(fifo)、時間片輪轉策略(rr)以及完全公平排程策略
對響應要求較高的實時系統一般採用先進先出策略或者時間片輪轉策略,而對於普通程序來說則採用完全公平排程策略,完全公平排程演算法會根據程序已占用cpu的時間來進行排序,並且程序獲取cpu後能夠執行的時間也是有其權重決定的,cpu會保證在某個時間週期內就緒佇列中的所有程序都至少獲取cpu執行一次,以此來達到完全公平排程的目的。
程序的排程切換所不得不涉及的兩個概念就是系統呼叫和中斷。
中斷為計算機提供了一種執行正常程式以外**的機制,如果沒有中斷機制就不存在多工的作業系統。中斷分為硬中斷和軟中斷,硬中斷是當cpu在執行每條指令後會檢查中斷訊號,如果有中斷請求便會中斷當前程式的執行去處理中斷,而系統呼叫是一種軟中斷,系統呼叫是程式從使用者態自陷入核心態以完成一些使用者態所不能完成的操作。
程序排程的大致過程可以描述為如下:
正在執行的使用者態程序發生中斷
cpu完成中斷上下文的切換(將ip、sp和flags暫存器中的值壓入核心棧中),載入相應中斷處理程式的ip
和sp
值到指令指標暫存器和棧頂指標暫存器中
在中斷處理程式的入口,對現場進行保護,此時程序由使用者態轉變為核心態完成中斷上下文切換
執行中斷處理程式,如果在此期間呼叫了程序排程函式schedule()
,則會進行相應的程序上下文切換,將當前核心棧的相關資訊儲存,切換為下乙個被排程進來的程序的核心棧
再由被排程進來的程序從排程函式返回到中斷處理程式最終返回至被排程進來的程序的使用者態繼續執行剩餘**
程序間有多種通訊方式:
管道套接字
共享記憶體
訊息佇列
訊號量等
管道在作業系統中非常的常見,例如在shell命令中就存在著管道的使用,如下命令就使用了管道
cat a.log | grep "hello world"
套接字在我們平常的網路通訊中非常常見,tcp連線就是使用了tcp套接字來完成的
在linux中存在許多的訊號,比如在命令列下我們按下ctrl + c
,核心會向程序傳送乙個sigint
訊號以終止當前正在執行的程序
剩下的一些通訊方式在此不過多描述
linux將虛擬記憶體劃分成固定大小的頁(linux中的頁大小是4kb),並且以頁作為操作記憶體的最小單元,從磁碟中都是一次性讀取一頁,每乙個程序都維護著乙個頁表,由於乙個頁表項(頁號、物理塊號、狀態位、訪問字段、修改位、外存位址等等)中可能存在大量的內容,因此對於乙個頁表進一步地進行劃分以解決頁表過大的問題。
linux中採取的是多級頁表方案,在頁目錄中,如果某個頁表中的所有頁表項均為無效的,那麼在記憶體中就不會維護這個頁表,即頁目錄中的記錄頁表的項在記憶體中不會分配頁來記錄它們,這樣就可以達到減小頁表大小的目的。
在linux系統中的任何乙個概念幾乎都可以看做乙個檔案。核心在非結構化的硬體上建立了乙個結構化的虛擬檔案系統,隱藏了各種硬體的具體細節,從而在整個系統的幾乎所有機制中使用檔案的抽象。linux在不同物理介質或虛擬結構上支援數十種檔案系統。
vfs 是底層檔案系統的主要介面。這個元件匯出一組介面,然後將它們抽象到各個檔案系統,各個檔案系統的行為可能差異很大。有兩個針對檔案系統物件的快取(inode
和dentry
)。它們快取最近使用過的檔案系統物件。在這裡緩衝區快取和裝置驅動的互動、以及vfs提供的系統介面暫不討論,主要看看實現這個vfs子系統的主要結構
裝置驅動程式包含與裝置進行通訊時所需的所有特定於裝置的**。此**包括一組用於系統其餘部分的標準介面。就像系統呼叫介面可使應用程式不受平台特定資訊影響一樣,此介面可保護核心不受裝置特定資訊的影響。應用程式和核心其餘部分需要非常少的特定於裝置的**(如果有)對此裝置進行定址。這樣,裝置驅動程式使得系統的可移植性更強,並更易於維護。
裝置驅動程式按照處理 i/o 的方式可以分為以下三大類別:
塊裝置驅動程式-適用於可將 i/o 資料作為非同步塊進行處理的情況。通常,塊驅動程式用於管理可物理定址的儲存介質的裝置,如磁碟。
字元裝置驅動程式-適用於針對連續的位元組流執行 i/o 操作的裝置。
streams 裝置驅動程式-字元驅動程式的子集,將 streamio(7i) 例程集用於核心中的字元 i/o
讀檔案流程
程序呼叫read()
庫函式
庫函式會將對應的引數封裝好,預處理後呼叫read()
庫函式對應的系統呼叫
核心通過檢查程序的檔案描述符定位到虛擬檔案系統的已開啟檔案列表表項
通過檔案表項鍊接到目錄項模組,根據傳入的檔案路徑,在目錄項模組中檢索,找到該檔案的inode
在inode
中,通過檔案內容偏移量計算出要讀取的頁
通過inode
找到檔案對應的address_space
在address_space
中訪問該檔案的頁快取樹,查詢對應的頁快取結點:
如果頁快取命中,那麼直接返回檔案內容;
如果頁快取缺失,那麼產生乙個頁缺失異常,建立乙個頁快取頁,同時通過inode
找到檔案該頁的磁碟位址,讀取相應的頁填充該快取頁;重新進行第6步查詢頁快取
硬體的速度:程式的執行需要將磁碟中靜態的程式載入到cpu中,而硬碟的速度相對cpu是程式執行的下限。同樣cpu效能至關重要。
快取的命中:現代計算機的構造中,有多級快取,在快取都命中的情況下,程式的執行速度是更快的。
缺頁異常:在頁命中時,計算機無需進行磁碟io操作,程式的執行速度是比頻繁發生缺頁異常的程式快的
上述的虛擬頁記憶體管理以及緩衝cache其實都是利用的區域性性原理,即cpu訪存時,無論是訪問指令還是訪問資料,所訪問的儲存單元都趨於聚集在乙個較小的連續區域中。
根據區域性性原理而引入了cache,在c語言中資料是以行優先的形式連續存放的,因此在編寫程式時,我們應該盡量以行優先的形式來遍歷陣列,以增加cache的命中次數,如果以列優先的方式來訪問陣列的話則會發生更多次的快取不命中和缺頁的情況,我們可以通過以下c程式,來對上述結論進行驗證
#include #include #define n 1000
// 行優先方式訪問double二維陣列
void rowfirst(double nums[n][n])
}}// 列優先方式訪問double二維陣列
void colfirst(double nums[n][n])
}}int main(void)
}// 計算行優先的執行時間
begin = clock();
for (int i = 0; i < n; i++)
end = clock();
duration = end - begin;
// 計算列優先的執行時間
根據執行結果可以看出按行訪問陣列的方式比按列訪問陣列的方式速度快了接近3倍,上述的結論是成立的。因此,編寫程式時應該盡量地去遵循區域性性原理,增加cache命中次數來保證程式的執行速度
從系統的角度分析影響程式執行效能的因素
從使用者的角度到系統底層的順序來看,linux系統包含以下幾個部分 應用程式 linux系統能夠執行的程式,用於完成使用者所希望的功能 shell程式 用於執行使用者所寫的或者自帶的應用程式 檔案系統 用於組織磁碟上的檔案,規定了檔案的組織和儲存方式 系統呼叫和公用函式庫 作業系統提供的功能函式以及...
hello程式的執行過程 從計算機系統角度
2 初始時,shell程式執行它的指令,等待我們輸入乙個命令。當我們在鍵盤上輸入字串 hello 後,shell程式將字元讀入cpu的暫存器中,再把它存放到主存中。3 當我們敲回車鍵時,結束命令的輸入,然後shell程式執行一系列指令來載入可執行的hello檔案,這些指令將hello目標檔案中的 和...
23 從物理執行的角度透視 spark job
即使採用pipeline的方式,函式f對依賴的rdd中的資料操作也會有兩種方式 1,f record f作用於集合的每一條記錄,每次只作用於一條記錄 2,f records f一次性作用於集合的全部資料 spark的實現,是採用第一種方式,為什麼採用第一種方式,原因 1,無需等待,可以最大化的使用集...