1.5.3 Linux內核的抽象結構
Linux內核由5個 主要的子系統組成:如圖1.2
圖1.2 Linux內核子系統及其之間的關系
1.進程調度(SCHED)控制着進程對CPU的訪問。當需要選擇下一個進程運行時,由調度程序選擇最值得運行的進程。可運行進程實際是僅等待 CPU 資源的進程,如果某個進程在等待其他資源,則該進程是不可運行進程。Linux 使用了比較簡單的基於優先級的進程調度算法選擇新的進程。
2.內存管理(MM)允許多個進程安全地共享主內存區域 。Linux的內存管理支持虛擬內存,即在計算機中運行的程序,其代碼、數據和堆棧的總量可以超過實際內存的大小,操作系統只將當前使用的程序塊保留在內存中,其余的程序塊則保留在磁盤上。必要時,操作系統負責在磁盤和內存之間交換程序塊。
內存管理從邏輯上可以分為硬件無關的部分和硬件相關的部分。硬件無關的部分提供了進程的映射和虛擬內存的對換;硬件相關的部分為內存管理硬件提供了虛擬接口。
3. 虛擬文件系統(VirtulFile System VFS)隱藏了各種不同硬件的具體細節,為所有設備提供了統一的接口,VFS還支持多達數十種不同的文件系統,這也是Linux較有特色的一部分。
虛擬文件系統可分為邏輯文件系統和設備驅動程序。邏輯文件系統指Linux所支持的文件系統,如ext2, fat等,設備驅動程序指為每一種硬件控制器所編寫的設備驅動程序模塊。
4.網絡接口(NET)提供了對各種網絡標准協議的存取和各種網絡硬件的支持。網絡接口可分為網絡協議和網絡驅動程序兩部分。網絡協議部分負責實現每一種可能的網絡傳輸協議,網絡設備驅動程序負責與硬件設備進行通信,每一種可能的硬件設備都有相應的設備驅動程序。
5. 進程間通信(IPC)支持進程間各種通信機制。
從圖1.2可以看出,處於中心位置的是進程調度,所有其它的子系統都依賴於它,因為每個子系統都需要掛起或恢復進程。一般情況下,當一個進程等待硬件操作完成時,它被掛起;當操作真正完成時,進程被恢復執行。例如,當一個進程通過網絡發送一條消息時,網絡接口需要掛起發送進程,直到硬件成功地完成消息的發送,當消息被發送出去以后,網絡接口給進程返回一個代碼,表示操作的成功或失敗。其它子系統(內存管理,虛擬文件系統及進程間通信)以相似的理由依賴於進程調度。
各個子系統之間的依賴關系如下:
· 進程調度與內存管理之間的關系:這兩個子系統互相依賴。在多道程序環境下,程序要運行必須為之創建進程,而創建進程的第一件事,就是要將程序和數據裝入內存。
· 進程間通信與內存管理的關系:進程間通信子系統要依賴內存管理支持共享內存通信機制,這種機制允許兩個進程除了擁有自己的私有內存,還可存取共同的內存區域。
·虛擬文件系統與網絡接口之間的關系:虛擬文件系統利用網絡接口支持網絡文件系統(NFS),也利用內存管理支持RAMDISK 設備。
· 內存管理與虛擬文件系統之間的關系: 內存管理利用虛擬文件系統支持交換,交換進程(swapd)定期地由調度程序調度,這也是內存管理依賴於進程調度的唯一原因。當一個進程存取的內存映射被換出時,內存管理向文件系統發出請求,同時,掛起當前正在運行的進程。
除了圖1.2所顯示的依賴關系以外,內核中的所有子系統還要依賴一些共同的資源,但在圖中並沒有顯示出來。這些資源包括所有子系統都用到的過程,例如,分配和釋放內存空間的過程,打印警告或錯誤信息的過程,還有系統的調試例程等等。
1.6 Linux內核源代碼
1.6.1 多版本的內核源代碼
對不同的內核版本,系統調用一般是相同的。新版本也許可以增加一個新的系統調用,但舊的系統調用將依然不變,這對於保持向后兼容是非常必要的—一個新的內核版本不能打破常規的過程。在大多數情況下,設備文件將仍然相同,而另一方面,版本之間的內部接口有所變化。
Linux內核源代碼有一個簡單的數字系統,任何偶數內核(如2.0.30)是一個穩定的版本,而奇數內核(如2.1.42)是正在發展中的內核。這本書是基於穩定的2.4.16 源代碼樹。發展中的內核總是有最新的特點,支持最新的設備,盡管它們還不穩定,也不是你所想要的,但它們是發展最新而又穩定的內核的基礎。
目前,較新而又穩定的內核版本是2.2.x和2.4.x,因為版本之間稍有差別,因此,如果你想讓一個新驅動程序模塊既支持2.2.x,也支持2.4.x,就需要根據內核版本對模塊進行條件編譯。
對內核源代碼的修改是以補丁文件的形式發布的。patch實用程序用來對內核源文件進行一系列的修訂,例如,如果你有2.4.9內核源代碼,而你想移到2.4.16,你可以獲得2.4.16的補丁文件,應用patch來修訂2.4.9源文件。例如:
$ cd/usr/src/linux
$ patch-p1 < patch-2.4.16
1.6.2 Linux內核源代碼的結構
Linux內核源代碼位於/usr/src/linux目錄下,其結構分布如圖1.3所示,每一個目錄或子目錄可以看作一個模塊,其目錄之間的連線表示“子目錄或子模塊”的關系。下面是對每一個目錄的簡單描述。
include/子目錄包含了建立內核代碼時所需的大部分包含文件,這個模塊利用其它模塊重建內核。
init/ 子目錄包含了內核的初始化代碼,這是內核開始工作的起點。
arch/子目錄包含了所有硬件結構特定的內核代碼,如圖1.3,arch/ 子目錄下有i386和alpha模塊等等。
drivers/ 目錄包含了內核中所有的設備驅動程序,如塊設備,scsi 設備驅動程序等等。
fs/ 目錄包含了所有文件系統的代碼,如:ext2, vfat模塊的代碼等等。
net/ 目錄包含了內核的連網代碼。
mm/ 目錄包含了所有的內存管理代碼。
ipc/ 目錄包含了進程間通信的代碼。
kernel/ 目錄包含了主內核代碼
圖1.3顯示了八個目錄,即 init, kernel, mm, ipc, drivers, fs, arch 及net 的包含文件都在"include/" 目錄下。在Linux內核中包含了 drivers, fs,arch及 net 模塊,這就使得Linux內核既不是一個層次式結構,也不是一個微內核結構,而是一個“整體式”結構。因為系統調用可以直接調用內核層,因此,該結構使得整個系統具有較高的性能,其缺點是內核修改起來比較困難,除非遵循嚴格的規則和編碼標准。
在圖1.3中所顯示的模塊結構,代表了一種工作分配單元,利用這種結構,我們期望Linus Torvalds能維護和增強內核的核心服務,即,init/,kernel/, mm/及 ipc/,其它的模塊drivers, fs, arch及net也可以作為工作單元,例如,可以分配一組人對塊文件系統進行維護和進一步的開發,而另一組人對scsi文件系統進行完善。圖1.3類似於Linux的自願者開發隊伍一起工作來增強和擴展整個系統的框架。
圖1.3 Linux源代碼的分布結構