歡迎光臨
每天分享高質量文章

【譯】Linux概念架構的理解

宣告:本文翻譯自Conceptual Architecture of the Linux Kernel


摘要

Linux kernel成功的兩個原因:(1)靈活的架構設計使得大量的志願開發者能夠很容易加入到開發過程中;(2)每個子系統(尤其是那些需要改進的)都具備良好的可擴展性。正是這兩個原因使得Linux kernel可以不斷進化和改進。

一、Linux內核在整個計算機系統中的位置

分層結構的原則:the dependencies between subsystems are from the top down: layers pictured near the top depend on lower layers, but subsystems nearer the bottom do not depend on higher layers.

這種子系統之間的依賴性只能是從上到下,也就是在上圖中位於頂層的子系統依賴位於底層的子系統,反之則不行。

二、內核的作用

  1. 虛擬化(抽象),將計算機硬體抽象為一臺虛擬機,供用戶行程(process)使用;行程運行時完全不需要知道硬體是如何工作的,只要呼叫Linux kernel提供的虛擬接口(virtual interface)即可。

  2. 多任務處理,實際上是多個任務在並行使用計算機硬體資源,內核的任務是仲裁對資源的使用,製造每個行程都以為自己是獨占系統的錯覺。

PS:行程背景關係切換就是要換掉程式狀態字、換掉頁表基地址暫存器的內容、換掉current指向的taskstruct實體、換掉PC——>也就換掉了行程打開的檔案(通過taskstruct的files可以找到)、換掉了行程記憶體的執行空間(通過task_struct的mem可以找到);

三、Linux內核的整體架構

中心系統是Process Scheduler(SCHED):所有其餘的子系統都依賴於Process Scheduler,因為其餘子系統都需要阻塞和恢復行程。當一個行程需要等待一個硬體動作完成時,相應子系統會阻塞這個行程;當這個硬體動作完成時,子系統會將這個行程恢復:這個阻塞和恢復動作都要依賴於Processor Scheduler完成。

上圖中的每一個依賴箭頭都有原因:

  • Process Scheduler依賴Memory manager:行程恢復執行時,需要依靠Memory Manager分配供它運行的記憶體。

  • IPC子系統依賴於Memory manager:共享記憶體機制是行程間通信的一種方法,運行兩個行程利用同一塊共享的記憶體空間進行信息傳遞。

  • VFS依賴於Network Interface:支持NFS網絡檔案系統;

  • VFS依賴於Memory Manager:支持ramdisk 設備

  • memory manager依賴於VFS,因為要支持swapping,可以將暫時不運行的行程換出到磁盤上的swap分割槽,進入掛起狀態。

四、高度模塊化設計的系統,利於分工合作

  1. 只有極少數的程式員需要橫跨多個模塊開展工作,這種情況確實會發生,僅發生在當前系統需要依賴另一個子系統時;

  2. 硬體設備驅動(hardware device drivers)、檔案系統模塊(logical filesystem modules)、網絡設備驅動(network device drivers)和網絡協議模塊(network protocol modules)這四個模塊的可擴展性最高。

五、系統中的資料結構

  1. Task List Process Scheduler 針對每個行程維護一個資料結構task_struct;所有的行程用鏈表管理,形成task list;process scheduler還維護一個current指標指向當前正在占用CPU的行程。

  2. Memory Map Memory Manager儲存每個行程的虛擬地址到物理地址的映射;並且也提供瞭如何換出特定的頁,或者是如何進行缺頁處理。這些信息存放在資料結構mmstruct中。每個行程都有一個mmstruct結構,在行程的taskstruct結構中有一個指標mm指向次行程的mmstruct結構。 在mm_struct中有一個指標pgd,指向該行程的頁目錄表(即存放頁目錄首地址)——>當該行程被調度時,此指標被換成物理地址,寫入控制暫存器CR3(x86體系結構下的頁基址暫存器)

  3. I-nodes VFS通過inodes節點表示磁盤上的檔案鏡像,inodes用於記錄檔案的物理屬性。每個行程都有一個filesstruct結構,用於表示該行程打開的檔案,在taskstruct中有個files指標。使用inodes節點可以實現檔案共享。檔案共享有兩種方式:(1)通過同一個系統打開檔案file指向同一個inodes節點,這種情況發生於父子行程間;(2)通過不同系統打開檔案指向同一個inode節點,舉例有硬鏈接;或者是兩個不相關的指標打開同一個檔案。

  4. Data Connection 內核中所有的資料結構的根都在Process Scheduler維護的task list鏈表中。系統中每個行程的的資料結構task_struct中有一個指標mm指向它的記憶體映射信息;也有一個指標files指向它打開的檔案(用戶打開檔案表);還有一個指標指向該行程打開的網絡套接字。

六、子系統架構

1. Process Scheduler 架構

(1)標的

process scheduler是Linux kernel中最重要的子系統。系統通過它來控制對CPU的訪問——不僅僅是用戶行程對CPU的訪問,也包括其餘子系統對CPU的訪問。

(2)模塊

調度策略模塊(scheduling policy module):決定哪個行程獲得對CPU的訪問權;調度策略應該讓所有行程盡可能公平得共享CPU。

  • 體系結構相關模塊(architecture-specific module)設計一組統一的抽象接口來屏蔽特定體系接口芯片的硬體細節。這個模塊與CPU交互以阻塞和恢復行程。這些操作包括獲取每個行程需要儲存的暫存器和狀態信息、執行彙編代碼來完成阻塞或者恢復操作。

  • 體系結構無關模塊(architecture-independent module) 與調度策略模塊交互將決定下一個執行的行程,然後呼叫體系結構相關的代碼去恢復那個行程的執行。不僅如此,這個模塊還會呼叫memory manager的接口來確保被阻塞的行程的記憶體映射信息被正確得儲存起來。

  • 系統呼叫接口模塊(system call interface) 允許用戶行程訪問Linux Kernel明確暴露給用戶行程的資源。通過一組定義合適的基本上不變的接口(POSIX標準),將用戶應用程式和Linux內核解耦,使得用戶行程不會受到內核變化的影響。

(3)資料表示

調度器維護一個資料結構——task list,其中的元素時每個活動的行程task_struct實體;這個資料結構不僅僅包含用來阻塞和恢復行程的信息,也包含額外的計數和狀態信息。這個資料結構在整個kernel層都可以公共訪問。

(4)依賴關係、資料流、控制流

正如前面提到過的,調度器需要呼叫memory manager提供的功能,去為需要恢復執行的行程選擇合適的物理地址,正因為如此,所以Process Scheuler子系統依賴於記憶體管理子系統。當其他內核子系統需要等待硬體請求完成時,它們都依賴於行程調度子系統進行行程的阻塞和恢復。這種依賴性通過函式呼叫和訪問共享的task list資料結構來體現。所有的內核子系統都要讀或者寫代表當前正在運行行程的資料結構,因此形成了貫穿整個系統的雙向資料流。

除了內核層的資料流和控制流,OS服務層還給用戶行程提供註冊定時器的接口。這形成了由調度器對用戶行程的控制流。通常喚醒睡眠行程的用例不在正常的控制流範圍,因為用戶行程無法預知何時被喚醒。最後,調度器與CPU交互來阻塞和恢復行程,這又形成它們之間的資料流和控制流——CPU負責打斷當前正在運行的行程,並允許內核調度其他的行程運行。

2. Memory Manager 架構

(1)標的

記憶體管理模塊負責控制行程如何訪問物理記憶體資源。通過硬體記憶體管理系統(MMU)管理行程虛擬記憶體和機器物理記憶體之間的映射。每一個行程都有自己獨立的虛擬記憶體空間,所以兩個行程可能有相同的虛擬地址,但是它們實際上在不同的物理記憶體區域運行。MMU提供記憶體保護,讓兩個行程的物理記憶體空間不互相干擾。記憶體管理模塊還支持swap——將暫時不用的記憶體頁換出到磁盤上的swap分割槽,這種技術讓行程的虛擬地址空間大於物理記憶體的大小。虛擬地址空間的大小由機器字長決定。

(2)模塊

  • 架構相關模塊(architecture specific module)提供訪問物理記憶體的虛擬接口;

  • 架構無關模塊(architecture independent module)負責每個行程的地址映射以及虛擬記憶體交換。當發生缺頁錯誤時,由該模塊負責決定哪個記憶體頁應該被換出記憶體——因為這個記憶體頁換出選擇演算法幾乎不需要改動,所以這裡沒有建立一個獨立的策略模塊。

  • 系統呼叫接口(system call interface) 為用戶行程提供嚴格的訪問接口(malloc和free;mmap和ummap)。這個模塊允許用行程分配和釋放記憶體、執行記憶體映射檔案操作。

(3)資料表示

記憶體管理存放每個行程的虛擬記憶體到物理記憶體的映射信息。這種映射信息存放在mmstruct結構實體中,這個實體的指標又存放在每個行程的taskstruct中。除了存放映射信息,資料塊中還應該存放關於記憶體管理器如何獲取和儲存頁的信息。例如:可執行代碼能夠將可執行鏡像作為備份儲存;但是動態申請的資料則必須備份到系統頁中。(這個沒看懂,請高手解惑?)
最後,記憶體管理模塊還應該存放訪問和技術信息,以保證系統的安全。

(4)依賴關係、資料流和控制流

記憶體管理器控制物理記憶體,當page fault發生時,接受硬體的通知(缺頁中斷)—— 這意味著在記憶體管理模塊和記憶體管理硬體之間存在雙向的資料流和控制流。記憶體管理也依賴檔案系統來支持swapping和記憶體映射I/O——這種需求意味著記憶體管理器需要呼叫對檔案系統提供的函式接口(procedure calls),往磁盤中存放記憶體頁和從磁盤中取記憶體頁。因為檔案系統請求非常慢,所以在等待記憶體頁被換入之前,記憶體管理器要讓行程需要進入休眠——這種需求讓記憶體管理器呼叫process scheduler的接口。由於每個行程的記憶體映射存放在行程調度器的資料結構中,所以在記憶體管理器和行程調度器之間也有雙向的資料流和控制流。用戶行程可以建立新的行程地址空間,並且能夠感知缺頁錯誤——這裡需要來自記憶體管理器的控制流。一般來說沒有用戶行程到記憶體管理器的資料流,但是用戶行程卻可以通過select系統呼叫,從記憶體管理器獲取一些信息。

3. Virtual File System 架構

(1)標的

虛擬檔案系統為儲存在硬體設備上資料提供統一的訪問接口。可以兼容不同的檔案系統(ext2,ext4,ntf等等)。計算機中幾乎所有的硬體設備都被表示為一個通用的設備驅動接口。邏輯檔案系統促進與其他操作系統標準的兼容性,並且允許開發者以不同的策略實現檔案系統。虛擬檔案系統更進一步,允許系統管理員在任何設備上掛載任何邏輯檔案系統。虛擬檔案系統封裝物理設備和邏輯檔案系統的細節,並且允許用戶行程使用統一的接口訪問檔案。

除了傳統的檔案系統標的,VFS也負責裝載新的可執行檔案。這個任務由邏輯檔案系統模塊完成,使得Linux可以支持多種可執行檔案。

(2)模塊

  • 設備驅動模塊(device driver module)

  • 設備獨立接口模塊(Device Independent Interface):提供所有設備的同一視圖

  • 邏輯檔案系統(logical file system):針對每種支持的檔案系統

  • 系統獨立接口(system independent interface)提供硬體資源和邏輯檔案系統都無關的接口,這個模塊通過塊設備節點或者字符設備節點提供所有的資源。

  • 系統呼叫模塊(system call interface)提供用戶行程對檔案系統的統一控制訪問。虛擬檔案系統為用戶行程屏蔽了所有特殊的特性。

(3)資料表示

所有檔案使用i-nodes表示。每個inode都記錄一個檔案在硬體設備上的位置信息。不僅如此,inode還存放著指向邏輯檔案系統模塊和設備驅動的的函式指標,這些指標能夠執行具體的讀寫操作。通過按照這種形式(就是面向物件中的虛函式的思想)存放函式指標,具體的邏輯檔案系統和設備驅動可以向內核註冊自己而不需要內核依賴具體的模塊特性。

(4)依賴關係、資料流和控制流

一個特殊的設備驅動是ramdisk,這個設備在主存中開闢一片區域,並把它當成持久性儲存設備使用。這個設備驅動使用記憶體管理模塊完成任務,所以在VFS與對記憶體管理模塊存在依賴關係(圖中的依賴關係反了,應該是VFS依賴於記憶體管理模塊)、資料流和控制流。

邏輯檔案系統支持網絡檔案系統。這個檔案系統像訪問本地檔案一樣,從另一臺機器上訪問檔案。為了實現這個功能,一種邏輯檔案系統通過網絡子系統完成它的任務——這引入了VFS對網絡子系統的一個依賴關係以及它們之間的控制流和資料流。

 正如前面提到的,記憶體管理器使用VFS完成記憶體swap功能和記憶體映射I/O。另外,當VFS等待硬體請求完成時,VFS需要使用行程調度器阻塞行程;當請求完成時,VFS需要通過行程調度器喚醒行程。最後,系統呼叫接口允許用戶行程呼叫來存取資料。不像前面的子系統,VFS沒有提供給用戶註冊不明確呼叫的機制,所以沒有從VFS到用戶行程的控制流。

4. Network Interface 架構

(1)標的

網絡子系統讓Linux系統能夠通過網絡與其他系統相連。這個子系統支持很多硬體設備,也支持很多網絡協議。網絡子系統將硬體和協議的實現細節都屏蔽掉,並抽象出簡單易用的接口供用戶行程和其他子系統使用——用戶行程和其餘子系統不需要知道硬體設備和協議的細節。

(2)模塊

  • 網絡設備驅動模塊(network device drivers)

  • 設備獨立接口模塊(device independent interface module)提供所有硬體設備的一致訪問接口,使得高層子系統不需要知道硬體的細節信息。

  • 網絡協議模塊(network protocol modules)負責實現每一個網絡傳輸協議,例如:TCP,UDP,IP,HTTP,ARP等等~

  • 協議無關模塊(protocol independent interface)提供獨立於具體協議和具體硬體設備的一致性接口。這使得其餘內核子系統無需依賴特定的協議或者設備就能訪問網絡。

  • 系統呼叫接口模塊(system calls interface)規定了用戶行程可以訪問的網絡編程API

(3)資料表示

每個網絡物件都被表示為一個套接字(socket)。套接字與行程關聯的方法和i-nodes節點相同。通過兩個task_struct指向同一個套接字,套接字可以被多個行程共享。

(4)資料流,控制流和依賴關係

當網絡子系統需要等待硬體請求完成時,它需要通過行程調度系統將行程阻塞和喚醒——這形成了網絡子系統和行程調度子系統之間的控制流和資料流。不僅如此,虛擬檔案系統通過網絡子系統實現網絡檔案系統(NFS)——這形成了VFS和網絡子系統指甲的資料流和控制流。

七、結論

1、Linux內核是整個Linux系統中的一層。內核從概念上由五個主要的子系統構成:行程調度器模塊、記憶體管理模塊、虛擬檔案系統、網絡接口模塊和行程間通信模塊。這些模塊之間通過函式呼叫和共享資料結構進行資料交互。、

2、Linux內核架構促進了他的成功,這種架構使得大量的志願開發人員可以合適得分工合作,並且使得各個特定的模塊便於擴展。

  • 可擴展性一:Linux架構通過一項資料抽象技術使得這些子系統成為可擴展的——每個具體的硬體設備驅動都實現為單獨的模塊,該模塊支持內核提供的統一的接口。通過這種方式,個人開發者只需要和其他內核開發者做最少的交互,就可以為Linux內核添加新的設備驅動。

  • 可擴展性二:Linux內核支持多種不同的體系結構。在每個子系統中,都將體系結構相關的代碼分割出來,形成單獨的模塊。通過這種方法,一些廠家在推出他們自己的芯片時,他們的內核開發小組只需要重新實現內核中機器相關的代碼,就可以講內核移植到新的芯片上運行。

參考文章:

  1. http://oss.org.cn/ossdocs/linux/kernel/a1/index.html

  2. http://www.cs.cmu.edu/afs/cs/project/able/www/paperabstracts/introsoftarch.html

  3. http://www.fceia.unr.edu.ar/ingsoft/monroe00.pdf

  4. 內核原始碼:http://lxr.oss.org.cn/

赞(0)

分享創造快樂