Robert Love:linux Kernel Development——a Thorough Guide To The Design And Implementation Of The Linux Kernel@2010 (第3版)

這份資料(目錄)詳細列出了 Robert Love 所著《Linux Kernel Development, Third Edition》一書的主要內容。本書旨在提供一個關於 Linux 核心設計、實作以及如何進行開發的實用指南。它深入探討了核心的各個關鍵子系統,協助讀者理解核心在不同情境下的行為與機制。核心的主要論點和涵蓋的關鍵領域可歸納如下:

核心基礎與開發環境

本書首先介紹了 Linux 核心的歷史,將其置於 Unix 作業系統發展的脈絡中,並概述了作業系統與核心的定義。接著,它指導讀者如何獲取、編譯和安裝核心原始碼,並指出核心開發與使用者空間程式設計的關鍵差異,例如缺乏標準 C 函式庫、對 GNU C 擴充的依賴、以及在核心空間中對記憶體保護的限制。這部分為讀者進入核心開發領域奠定了基礎,強調了原始碼、社群以及對核心特殊環境的理解的重要性。

處理程序管理與排程

本書詳細闡述了 Linux 核心如何管理處理程序(或稱任務),包括處理程序描述符 struct task_struct 的結構與分配,處理程序狀態的轉換,處理程序上下文的概念,以及處理程序的創建(fork, vfork, clone)與終止(exit)機制。核心獨特的執行緒實作,視執行緒為共享資源的特殊處理程序,也在這部分進行了介紹。

緊隨處理程序管理的是處理程序排程。本書探討了多任務處理的概念,並深入介紹了 Linux 的排程策略,特別是完全公平排程器(CFS)的原理、目標與實作細節。CFS 引入了「公平」的概念,目標是模擬一個理想的多任務處理器,確保每個處理程序都能獲得公平的處理器時間比例,而非固定時間片。排程器的實作涵蓋了時間記帳、處理程序選擇(利用紅黑樹)、以及處理程序的睡眠與喚醒機制。此外,也討論了核心搶佔、使用者搶佔以及即時排程策略。

系統呼叫介面

系統呼叫是使用者空間程式與核心互動的唯一標準介面。本書解釋了系統呼叫的原理、其與 API 及 C 函式庫的關係,以及核心如何處理系統呼叫(包括系統呼叫號、參數傳遞和處理程序)。它還詳細說明如何在核心中實作新的系統呼叫,並強調了參數驗證(特別是使用者空間指標的安全存取)和避免不必要地新增系統呼叫的考量,鼓勵開發者優先使用現有的核心介面。

核心資料結構與演算法複雜度

為了在核心環境中高效地組織和操作資料,Linux 核心提供了多種內建的通用資料結構。本書介紹了連結串列(包括其在核心中的獨特實作)、佇列(特別是 kfifo)、映射(idr)以及二元樹(紅黑樹 rbtree)。理解這些資料結構的特性和適用場景對於編寫高效的核心程式至關重要。此外,本書也引入了演算法複雜度的概念,特別是 Big-O 表示法,用於評估演算法和資料結構的效能與可擴展性。

中斷、下半部與延遲工作

硬體透過中斷機制與核心溝通。本書詳細描述了中斷的產生和核心處理中斷的方式,特別是中斷處理常式(上半部)的角色和限制。由於中斷處理常式需要在中斷禁用或受限的環境中快速執行,許多工作必須延遲到更合適的時間再執行,這部分工作稱為下半部。本書探討了延遲工作的必要性,並介紹了 Linux 提供的多種下半部機制,包括 softirq、tasklet 和工作佇列(work queue)。softirq 用於處理高頻率、對延遲敏感的工作;tasklet 是基於 softirq 的更易用的機制;工作佇列則將工作延遲到核心執行緒中執行,允許阻塞操作。選擇合適的下半部機制取決於工作的特性和對上下文的要求。

核心同步機制

在多處理器系統或支持核心搶佔的環境中,多個執行緒可能同時存取共享資源,導致競賽條件。本書深入探討了核心同步的重要性,介紹了競賽條件、臨界區和死鎖的概念。為了防止競賽條件,核心提供了多種同步原語。本書詳細闡述了這些原語的使用與實作,包括原子操作(針對整數和位元)、自旋鎖(spinlock,在等待時忙等待)、號誌(semaphore,在等待時休眠)和互斥鎖(mutex,號誌的簡化版本)。還討論了不太常見的完成變數(completion variable)、大核心鎖(BKL,已不鼓勵使用)、順序鎖(seqlock)以及核心搶佔的禁用與記憶體屏障。選擇正確的同步機制對於編寫安全且高效的核心程式至關重要。

計時器與時間管理

核心對時間的感知是許多子系統的基礎。本書探討了核心的時間概念,包括定時器中斷、核心時鐘頻率(HZ)、jiffies 變數以及時間管理硬體(如即時時鐘 RTC 和系統定時器)。它詳細解釋了定時器中斷處理常式的職責,包括更新系統時間和執行排程任務。此外,本書還介紹了動態計時器(dynamic timers),用於排程一次性事件在指定時間後執行,並討論了在核心中延遲執行的各種方法。

記憶體管理

核心的記憶體管理比使用者空間複雜得多,需要直接處理物理記憶體和虛擬記憶體的對應。本書介紹了核心記憶體管理的基本單位:頁(page)和區域(zone),並詳細闡述了核心分配記憶體的各種機制。這包括低階的頁分配器(alloc_pages, get_free_pages)用於分配物理連續的頁,kmalloc 用於分配位元組級別的物理連續記憶體,以及 vmalloc 用於分配虛擬連續但不一定物理連續的記憶體。本書還重點介紹了 Slab 分配器,它用於高效地快取和管理常用資料結構物件。此外,也討論了核心堆疊的分配、高記憶體(highmem)的映射以及每處理程序(per-CPU)資料的分配與管理。理解這些分配器及其使用時的標誌(gfp_mask)對於正確、安全地在核心中獲取記憶體至關重要。

檔案系統與區塊 I/O

虛擬檔案系統(VFS)層提供了抽象介面,使得核心和使用者空間能夠以統一的方式存取各種檔案系統和儲存裝置。本書介紹了 VFS 的概念、Unix 檔案系統模型(檔案、目錄項、索引節點 inode 和超級區塊 superblock)以及 VFS 的核心物件和其操作集。

區塊 I/O 層處理與區塊裝置(如硬碟)的互動。本書描述了區塊裝置的結構、緩衝區(buffer head)的概念以及表示區塊 I/O 操作的新結構 bio。為了解決磁碟搜尋的低效性,區塊 I/O 層實現了 I/O 排程器(I/O scheduler),用於合併、排序和排程區塊請求,以優化磁碟吞吐量和延遲。本書介紹了幾種主要的 I/O 排程器(如 Deadline, Anticipatory, CFQ, Noop)及其原理。

裝置與模組

核心通過裝置驅動程式與硬體互動。本書介紹了裝置的三種類型(區塊、字元、網路),以及核心如何通過模組機制實現代碼的動態載入與卸載。這提高了核心的靈活性和可維護性。此外,還詳細介紹了裝置模型(device model),包括 kobject、kset 和 ktype 等結構,它們提供了一個統一的框架來表示系統中的裝置及其層次結構,並通過 sysfs 檔案系統將這個裝置樹暴露給使用者空間。這也為熱插拔裝置和電源管理提供了基礎。

除錯與可移植性

除錯是核心開發中具有挑戰性的一環。本書提供了核心除錯的實用技巧,包括使用 printk 進行列印除錯、分析 Oops 錯誤(包括 ksymoopskallsyms 的使用)、核心除錯選項、使用 BUG()panic() 進行斷言與錯誤報告、Magic SysRq 鍵的使用,以及如何使用 gdbkgdb 等工具。它還介紹了通過二分搜尋法來定位引入錯誤的特定提交。

可移植性是 Linux 的一個重要特性,使得核心能夠支援眾多不同的硬體架構。本書闡述了編寫可移植核心程式碼的關鍵考慮因素,包括資料型別(不同大小的 int, long, 指標)、資料對齊、位元組順序(大小端)、定時器頻率(HZ)以及處理器指令重排等。強調了在編寫通用程式碼時,應避免對硬體特性做出假設,並針對最保守的狀況提供適當的保護。

補丁、開發與社群

最後,本書討論了參與 Linux 核心開發社群的方式。它介紹了社群的主要交流平台 Linux Kernel Mailing List (LKML),以及被社群普遍接受的程式碼風格規範。解釋了如何生成和提交補丁(patch)來分享你的程式碼修改,以及如何報告錯誤和與社群協作。

總之,《Linux Kernel Development》第三版從核心的基礎概念、核心子系統的詳細實作,到開發工具和社群協作,提供了一個全面而實用的指南。它強調了理解核心內部機制對於有效開發的重要性,並為讀者提供了在實際專案中可能遇到的問題的解決方案和最佳實踐。