作業系統的設計與實作 (OS Design and Implementation)
本系列文章內容參考自經典教材 Operating System Concepts, 10th Edition (Silberschatz, Galvin, Gagne)。本文對應章節:Section 2.7 Operating-System Design and Implementation。
2.7.1 設計目標 (Design Goals)
設計一個作業系統的第一個問題,是定義目標與規格 (Goals and Specifications)。這件事看起來理所當然,但實際上非常困難,因為沒有任何教科書或公式能告訴你「正確答案」是什麼。不同的硬體、不同的使用場景,對 OS 的要求可以截然不同。
為什麼沒有通用解?
OS 的設計從一開始就受到兩個因素的高度約束:
- 硬體選擇:CPU 架構、記憶體大小、I/O 裝置的種類,直接決定了 OS 能做什麼、不能做什麼。
- 系統類型:一台傳統桌機、一台行動裝置、一台分散式伺服器叢集,或一個嵌入式即時控制系統,對 OS 的期待完全不同。
以兩個極端為例:Wind River VxWorks 是一個為嵌入式系統設計的即時 OS(Real-Time OS),它的首要目標是「在嚴格的時間限制內準確回應事件」;而 Windows Server 是為企業環境設計的大型多使用者 OS,首要目標是「支援大量使用者同時存取各種服務」。這兩個 OS 面對的問題截然不同,自然不可能有相同的設計。
使用者目標與系統目標
跨越這些差異,需求可以分成兩個大群體:
使用者目標 (User Goals):從使用系統的人的角度出發,OS 應該:
- 方便使用 (Convenient to use):介面直觀,不需要記住複雜指令
- 易於學習 (Easy to learn):上手門檻低
- 可靠 (Reliable):不輕易當機、資料不會無故消失
- 安全 (Safe):能防範惡意程式和未授權存取
- 快速 (Fast):回應時間短,不讓使用者等待
系統目標 (System Goals):從設計、開發、維運 OS 的工程師的角度出發,OS 應該:
- 易於設計與實作 (Easy to design and implement):設計不應過度複雜
- 易於維護 (Easy to maintain):日後修改功能或修復錯誤不應牽一髮動全身
- 靈活 (Flexible):能在不大改底層的情況下支援不同的策略
- 可靠且無錯誤 (Reliable and error-free):核心功能正確,不出現難以預測的行為
- 高效 (Efficient):不浪費 CPU、記憶體、I/O 等資源
仔細看這兩組目標,每一條都是正確的廢話。「要快、要可靠、要好用」,沒有人會反對這些。但當工程師真正坐下來設計 OS 的時候,這些目標對做具體決策幾乎沒有幫助,因為它們都太模糊了, 而且往往相互衝突:要「快」可能需要取捨「可靠」;要「靈活」可能犧牲「效率」。
這就是 OS 設計的真正挑戰:在模糊的目標下,針對特定的硬體和使用場景,做出一系列有取捨的具體決策。沒有任何通用方案可以在所有維度上同時最佳化。
2.7.2 機制與策略 (Mechanisms and Policies)
OS 設計中有一條最重要的軟體工程原則:機制與策略的分離 (Separation of Policy from Mechanism)。
機制與策略分別是什麼?
一個直觀的比喻是:假設公司設計了一套打卡系統。「打卡機的硬體電路如何記錄刷卡動作」是機制,「員工每天可以遲到幾分鐘」是策略。兩者是完全獨立的問題。
套回 OS 的語言:
- 機制 (Mechanism):決定如何做某件事 (How)。機制是底層的實作手段,定義系統能提供哪些能力。
- 策略 (Policy):決定要做什麼 (What)。策略是在機制之上,決定這些能力應該被如何使用。
教科書中的典型例子:Timer(計時器) 是一個機制,它提供了「在一段時間後觸發中斷、強制 CPU 回到 OS」的能 力(參見 Section 1.4.3)。但「Timer 應該設定為多長時間」是策略,由 OS 根據當前的排程政策決定。Timer 這個機制本身,無論策略如何改變,都不需要被修改。
為什麼分離很重要?
如果機制和策略緊密耦合在一起,那麼每當需要改變策略,就必須同時修改機制的程式碼。這會造成兩個問題:
- 修改成本高:改一個「要做什麼」的決策,卻需要動到底層的「如何做」的程式碼,容易引入錯誤。
- 難以適應變化:策略通常會隨著時間推移或不同環境而改變(例如,不同的伺服器工作負載需要不同的 CPU 排程策略),但機制應該是穩定的。
正確的做法是設計一個足夠通用、彈性夠強的機制,讓它能夠支援不同策略,然後把策略決策獨立出來,放在另一個容易替換的地方。當策略改變時,只需要修改策略層的參數,底層機制完全不需要變動。
以 CPU 排程的優先權為例:如果系統設計了一個「可以為不同類型的程式設定優先級」的機制,那麼:
- 策略 A:I/O 密集型程式優先(適合互動式桌面系統,讓 UI 回應更流暢)
- 策略 B:CPU 密集型程式優先(適合批次計算工作負載)
兩種策略可以直接切換,底層的優先權排程機制完全不需要改動。