Linux核心基礎
楔子
這部分的內容首先要回憶一下計算機的基礎知識,基本的計算機結構包括CPU(算數邏輯單元ALU、控制單元CU)、儲存器、輸入和輸出。CPU和其它裝置是透過匯流排連線的。CPU執行的基礎被稱為指令集,CPU執行儲存器存取指令時:CPU發出存取訊號,然後就從儲存器存取資料。存取器透過中斷機制通知CPU存取完畢。引入中斷機制的意義是,讓CPU不必等IO的完畢,而轉去執行其它指令。
計算機系統核心
核心的作用:
- 資源管理
- 提供基礎庫
傳統意義上的核心實現有兩種方式:
- 微核心結構:只有最基礎的功能由中央核心實現,其它的功能都由一些其它程序實現。
- 單核心結構;單核心還包括有檔案系統、記憶體管理、裝置驅動程式功能。Linux核心屬於單核心。
虛擬地址空間
記憶體區域是透過指標定址的,CPU字長決定了能夠管理的地址空間的最大長度。現代計算機支援64位的字長,所以其管理的最大虛擬記憶體空間大小為 264B,實際可定址的區域小於這個值。Linux將虛擬地址空間劃分為兩個部分:
- 核心空間,TASK_SIZE~264保留給核心專用,使用者程序無法訪問。
- 使用者空間,從0~TASK_SIZE是使用者空間範圍
使用者程序執行系統呼叫時,會發生使用者狀態到核心狀態的切換,切換到核心空間後,由核心程序去執行相應的任務。每個程序都認為它佔有全部的使用者空間。
頁表
虛擬地址空間和實體地址空間之間對映的問題是透過頁表來實現的。實體地址和虛擬地址都被劃分為頁。程序A和程序B都擁有同樣大小的虛擬地址空間,但是他們需要訪問的資源不同,也就是需要訪問的實體地址不同,所有隻需要將其需要的訪問的虛擬頁對映到真實物理頁即可。物理頁經常被稱為頁幀,頁一般指虛擬地址空間的頁。
頁表的設計
每個頁表項資料結構中包含虛擬地址頁以及與其相對應的頁幀。如果只有一層,假如每頁都是1KB,那麼1GB就需要儲存100個頁表項,那麼此時會很耗記憶體,所以實際設計方式中採用層次設計原理。Linux採用了四層頁表:
- 全域性頁目錄(Page Global Directory, PGD)
- 中間頁目錄(Page Middle Directory, PMD)
- 頁表陣列(Page Table Entry, PTE)
然後進行層級查詢即可,此時不需要使用的虛擬地址空間,就不會有中間頁目錄、頁表陣列等。避免只用一個陣列項儲存資料而佔用大量的記憶體。
層級設計存在的另一個問題是必須透過多層轉換才能夠訪問到實體地址。所以核心有兩種加速的方式:
- MMU(記憶體管理單元)最佳化記憶體訪問操作
- 儲存到TLB(Translation Lookaside Buffer)(CPU緩衝區)轉移後備緩衝區將頻繁使用的地址儲存在其中,避免直接查詢頁表,節約時間。
實體記憶體的分配
- 夥伴系統:記憶體分配中經常需要分配連續的頁
- slab緩衝:本質上用於更小的分配記憶體單元(從頁中分配)
頁面交換和頁面回收
頁面交換是透過缺頁異常實現的。頁面回收其實就是頁面回寫,將資料寫入到硬碟中。
外設
- 塊裝置:可以隨機訪問資料,典型的就是硬碟,資料的讀寫只能以塊(一般為512B)的倍數讀寫,按塊讀寫。
- 字元裝置:順序讀取,通常不支援隨機存取。按字元/位元組讀寫資料。
快取
從低速塊裝置讀取資料暫存在記憶體中,一般快取也是按頁組織的,稱為頁快取。