一、linux核心在整個計算機系統中的位置
fig 1 - 計算機系統分層結構
分層結構的原則: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 指向的 task_struct 執行個體、換掉 pc ——>也就換掉了程序打開的檔案(通過 task_struct 的 files 可以找到)、換掉了程序記憶體的執行空間(通過 task_struct 的 mem 可以找到)。
三、linux核心的整體架構
linux核心的整體架構
中心系統是程序排程器process scheduler,sched:所有其餘的子系統都依賴于程序排程器,因為其餘子系統都需要阻塞和恢複程序。當一個程序需要等待一個硬體動作完成時,相應子系統會阻塞這個程序;當這個硬體動作完成時,子系統會将這個程序恢複:這個阻塞和恢複動作都要依賴于程序排程器完成。
上圖中的每一個依賴箭頭都有原因:
◆程序排程器依賴記憶體管理器memory manager:程序恢複執行時,需要依靠記憶體管理器配置設定供它運作的記憶體。
◆ipc 子系統依賴于記憶體管理器:共享記憶體機制是程序間通信的一種方法,運作兩個程序利用同一塊共享的記憶體空間進行資訊傳遞。
◆vfs 依賴于網絡接口network interface:支援 nfs 網絡檔案系統;
◆vfs 依賴于記憶體管理器:支援 ramdisk 裝置
◆記憶體管理器依賴于 vfs,因為要支援交換swapping,可以将暫時不運作的程序換出到磁盤上的交換分區swap,進入挂起狀态。
四、高度子產品化設計的系統,利于分工合作
隻有極少數的程式員需要橫跨多個子產品開展工作,這種情況确實會發生,僅發生在目前系統需要依賴另一個子系統時。
硬體裝置驅動hardware device drivers、檔案系統子產品logical filesystem modules、網絡裝置驅動network device drivers和網絡協定子產品network protocol modules這四個子產品的可擴充性最高。
五、系統中的資料結構
1.任務清單task list
程序排程器針對每個程序維護一個資料結構 task_struct;所有的程序用連結清單管理,形成 task list;程序排程器還維護一個 current 指針指向目前正在占用 cpu 的程序。
2.記憶體映射memory map
記憶體管理器存儲每個程序的虛拟位址到實體位址的映射;并且也提供了如何換出特定的頁,或者是如何進行缺頁處理。這些資訊存放在資料結構 mm_struct 中。每個程序都有一個 mm_struct 結構,在程序的 task_struct 結構中有一個指針 mm 指向次程序的 mm_struct 結構。
在 mm_struct 中有一個指針 pgd,指向該程序的頁目錄表(即存放頁目錄首位址)——>當該程序被排程時,此指針被換成實體位址,寫入控制寄存器 cr3(x86體系結構下的頁基址寄存器)。
3.i-nodes
vfs 通過 inodes 節點表示磁盤上的檔案鏡像,inodes 用于記錄檔案的實體屬性。每個程序都有一個 files_struct 結構,用于表示該程序打開的檔案,在 task_struct 中有個 files 指針。使用 inodes 節點可以實作檔案共享。檔案共享有兩種方式:(1)通過同一個系統打開檔案 file 指向同一個 inodes 節點,這種情況發生于父子程序間;(2)通過不同系統打開檔案指向同一個 inode 節點,舉例有硬連結;或者是兩個不相關的指針打開同一個檔案。
4.資料連接配接data connection
核心中所有的資料結構的根都在程序排程器維護的任務清單連結清單中。系統中每個程序的的資料結構 task_struct 中有一個指針 mm 指向它的記憶體映射資訊;也有一個指針 files 指向它打開的檔案(使用者打開檔案表);還有一個指針指向該程序打開的網絡套接字。
六、子系統架構
1.程序排程器process scheduler 架構
(1)目标
程序排程器是 linux kernel 中最重要的子系統。系統通過它來控制對 cpu 的通路——不僅僅是使用者程序對 cpu 的通路,也包括其餘子系統對 cpu 的通路。
(2)子產品
程序排程器
排程政策子產品scheduling policy module:決定哪個程序獲得對 cpu 的通路權;排程政策應該讓所有程序盡可能公平得共享 cpu。
◆體系結構相關子產品architecture-specific module設計一組統一的抽象接口來屏蔽特定體系接口晶片的硬體細節。這個子產品與 cpu 互動以阻塞和恢複程序。這些操作包括擷取每個程序需要儲存的寄存器和狀态資訊、執行彙編代碼來完成阻塞或者恢複操作。
◆體系結構無關子產品architecture-independent module與排程政策子產品互動将決定下一個執行的程序,然後調用體系結構相關的代碼去恢複那個程序的執行。不僅如此,這個子產品還會調用記憶體管理器的接口來確定被阻塞的程序的記憶體映射資訊被正确得儲存起來。
◆系統調用接口子產品system call interface允許使用者程序通路 linux kernel 明确暴露給使用者程序的資源。通過一組定義合适的基本上不變的接口(posix 标準),将使用者應用程式和 linux 核心解耦,使得使用者程序不會受到核心變化的影響。
(3)資料表示
排程器維護一個資料結構——task list,其中的元素是每個活動的程序 task_struct 執行個體;這個資料結構不僅僅包含用來阻塞和恢複程序的資訊,也包含額外的計數和狀态資訊。這個資料結構在整個 kernel 層都可以公共通路。
(4)依賴關系、資料流、控制流
正如前面提到過的,排程器需要調用記憶體管理器提供的功能,去為需要恢複執行的程序選擇合适的實體位址,正因為如此,是以程序排程器子系統依賴于記憶體管理子系統。當其他核心子系統需要等待硬體請求完成時,它們都依賴于程序排程子系統進行程序的阻塞和恢複。這種依賴性通過函數調用和通路共享的 task list 資料結構來展現。所有的核心子系統都要讀或者寫代表目前正在運作程序的資料結構,是以形成了貫穿整個系統的雙向資料流。
除了核心層的資料流和控制流,os 服務層還給使用者程序提供注冊定時器的接口。這形成了由排程器對使用者程序的控制流。通常喚醒睡眠程序的用例不在正常的控制流範圍,因為使用者程序無法預知何時被喚醒。最後,排程器與 cpu 互動來阻塞和恢複程序,這又形成它們之間的資料流和控制流——cpu 負責打斷目前正在運作的程序,并允許核心排程其他的程序運作。
2.記憶體管理器memory manager 架構
記憶體管理子產品負責控制程序如何通路實體記憶體資源。通過硬體記憶體管理系統(mmu)管理程序虛拟記憶體和機器實體記憶體之間的映射。每一個程序都有自己獨立的虛拟記憶體空間,是以兩個程序可能有相同的虛拟位址,但是它們實際上在不同的實體記憶體區域運作。mmu 提供記憶體保護,讓兩個程序的實體記憶體空間不互相幹擾。記憶體管理子產品還支援交換——将暫時不用的記憶體頁換出到磁盤上的交換分區,這種技術讓程序的虛拟位址空間大于實體記憶體的大小。虛拟位址空間的大小由機器字長決定。
記憶體管理子系統
◆架構相關子產品architecture specific module提供通路實體記憶體的虛拟接口。
◆架構無關子產品architecture independent module負責每個程序的位址映射以及虛拟記憶體交換。當發生缺頁錯誤時,由該子產品負責決定哪個記憶體頁應該被換出記憶體——因為這個記憶體頁換出選擇算法幾乎不需要改動,是以這裡沒有建立一個獨立的政策子產品。
◆系統調用接口system call interface為使用者程序提供嚴格的通路接口(malloc 和 free;mmap 和 ummap)。這個子產品允許用程序配置設定和釋放記憶體、執行記憶體映射檔案操作。
記憶體管理存放每個程序的虛拟記憶體到實體記憶體的映射資訊。這種映射資訊存放在 mm_struct 結構執行個體中,這個執行個體的指針又存放在每個程序的 task_struct 中。除了存放映射資訊,資料塊中還應該存放關于記憶體管理器如何擷取和存儲頁的資訊。例如:可執行代碼能夠将可執行鏡像作為備份存儲;但是動态申請的資料則必須備份到系統頁中。(這個沒看懂,請高手解惑?)
最後,記憶體管理子產品還應該存放通路和技術資訊,以保證系統的安全。
(4)依賴關系、資料流和控制流
記憶體管理器控制實體記憶體,當頁面失敗 page fault 發生時,接受硬體的通知(缺頁中斷)—— 這意味着在記憶體管理子產品和記憶體管理硬體之間存在雙向的資料流和控制流。記憶體管理也依賴檔案系統來支援交換和記憶體映射 i/o——這種需求意味着記憶體管理器需要調用對檔案系統提供的函數接口procedure calls,往磁盤中存放記憶體頁和從磁盤中取記憶體頁。因為檔案系統請求非常慢,是以在等待記憶體頁被換入之前,記憶體管理器要讓程序需要進入休眠——這種需求讓記憶體管理器調用程序排程器的接口。由于每個程序的記憶體映射存放在程序排程器的資料結構中,是以在記憶體管理器和程序排程器之間也有雙向的資料流和控制流。使用者程序可以建立新的程序位址空間,并且能夠感覺缺頁錯誤——這裡需要來自記憶體管理器的控制流。一般來說沒有使用者程序到記憶體管理器的資料流,但是使用者程序卻可以通過 select 系統調用,從記憶體管理器擷取一些資訊。
3.虛拟檔案系統virtual file system 架構
虛拟檔案系統為存儲在硬體裝置上資料提供統一的通路接口。可以相容不同的檔案系統(ext2,ext4,ntf等等)。計算機中幾乎所有的硬體裝置都被表示為一個通用的裝置驅動接口。邏輯檔案系統促進與其他作業系統标準的相容性,并且允許開發者以不同的政策實作檔案系統。虛拟檔案系統更進一步,允許系統管理者在任何裝置上挂載任何邏輯檔案系統。虛拟檔案系統封裝實體裝置和邏輯檔案系統的細節,并且允許使用者程序使用統一的接口通路檔案。
除了傳統的檔案系統目标,vfs 也負責裝載新的可執行檔案。這個任務由邏輯檔案系統子產品完成,使得 linux 可以支援多種可執行檔案。
虛拟檔案系統子產品
◆裝置驅動子產品device driver module
◆裝置獨立接口子產品device independent interface:提供所有裝置的同一視圖。
◆邏輯檔案系統logical file system:針對每種支援的檔案系統。
◆系統獨立接口system independent interface提供硬體資源和邏輯檔案系統都無關的接口,這個子產品通過塊裝置節點或者字元裝置節點提供所有的資源。
◆系統調用子產品system call interface提供使用者程序對檔案系統的統一控制通路。虛拟檔案系統為使用者程序屏蔽了所有特殊的特性。
所有檔案使用 inode 表示。每個 inode 都記錄一個檔案在硬體裝置上的位置資訊。不僅如此,inode 還存放着指向邏輯檔案系統子產品和裝置驅動的的函數指針,這些指針能夠執行具體的讀寫操作。通過按照這種形式(就是面向對象中的虛函數的思想)存放函數指針,具體的邏輯檔案系統和裝置驅動可以向核心注冊自己而不需要核心依賴具體的子產品特性。
一個特殊的裝置驅動是 ramdisk,這個裝置在主存中開辟一片區域,并把它當成持久性儲存設備使用。這個裝置驅動使用記憶體管理子產品完成任務,是以在 vfs 與對記憶體管理子產品存在依賴關系(圖中的依賴關系反了,應該是 vfs 依賴于記憶體管理子產品)、資料流和控制流。
邏輯檔案系統支援網絡檔案系統。這個檔案系統像通路本地檔案一樣,從另一台機器上通路檔案。為了實作這個功能,一種邏輯檔案系統通過網絡子系統完成它的任務——這引入了 vfs 對網絡子系統的一個依賴關系以及它們之間的控制流和資料流。
正如前面提到的,記憶體管理器使用 vfs 完成記憶體交換功能和記憶體映射 i/o。另外,當 vfs 等待硬體請求完成時,vfs 需要使用程序排程器阻塞程序;當請求完成時,vfs 需要通過程序排程器喚醒程序。最後,系統調用接口允許使用者程序調用來存取資料。不像前面的子系統,vfs 沒有提供給使用者注冊不明确調用的機制,是以沒有從vfs到使用者程序的控制流。
4.網絡接口network interface 架構
網絡子系統讓 linux 系統能夠通過網絡與其他系統相連。這個子系統支援很多硬體裝置,也支援很多網絡協定。網絡子系統将硬體和協定的實作細節都屏蔽掉,并抽象出簡單易用的接口供使用者程序和其他子系統使用——使用者程序和其餘子系統不需要知道硬體裝置和協定的細節。
網絡協定層子產品圖
◆網絡裝置驅動子產品network device drivers
◆裝置獨立接口子產品device independent interface module提供所有硬體裝置的一緻通路接口,使得高層子系統不需要知道硬體的細節資訊。
◆網絡協定子產品network protocol modules負責實作每一個網絡傳輸協定,例如:tcp,udp,ip,http,arp等等~
◆協定無關子產品protocol independent interface提供獨立于具體協定和具體硬體裝置的一緻性接口。這使得其餘核心子系統無需依賴特定的協定或者裝置就能通路網絡。
◆系統調用接口子產品system calls interface規定了使用者程序可以通路的網絡程式設計api。
每個網絡對象都被表示為一個套接字socket。套接字與程序關聯的方法和 inode 節點相同。通過兩個 task_struct 指向同一個套接字,套接字可以被多個程序共享。
(4)資料流,控制流和依賴關系
當網絡子系統需要等待硬體請求完成時,它需要通過程序排程系統将程序阻塞和喚醒——這形成了網絡子系統和程序排程子系統之間的控制流和資料流。不僅如此,虛拟檔案系統通過網絡子系統實作網絡檔案系統(nfs)——這形成了 vfs 和網絡子系統指甲的資料流和控制流。
七、結論
1.linux 核心是整個 linux 系統中的一層。核心從概念上由五個主要的子系統構成:程序排程器子產品、記憶體管理子產品、虛拟檔案系統、網絡接口子產品和程序間通信子產品。這些子產品之間通過函數調用和共享資料結構進行資料互動。
2.linux 核心架構促進了他的成功,這種架構使得大量的志願開發人員可以合适得分工合作,并且使得各個特定的子產品便于擴充。
◆可擴充性一:linux 架構通過一項資料抽象技術使得這些子系統成為可擴充的——每個具體的硬體裝置驅動都實作為單獨的子產品,該子產品支援核心提供的統一的接口。通過這種方式,個人開發者隻需要和其他核心開發者做最少的互動,就可以為 linux 核心添加新的裝置驅動。
◆可擴充性二:linux 核心支援多種不同的體系結構。在每個子系統中,都将體系結構相關的代碼分割出來,形成單獨的子產品。通過這種方法,一些廠家在推出他們自己的晶片時,他們的核心開發小組隻需要重新實作核心中機器相關的代碼,就可以講核心移植到新的晶片上運作。
作者:ivan bowman
來源:51cto