本節討論作業系統設計和實現面臨的問題。雖然這些問題沒有完整的解決方案,但是有些方法還是行之有效的。
設計目標
系統設計的首要問題是,定義目標和規範。從高層來說,系統設計取決於所選硬體和系統型別:批次處理、分時、單使用者、多使用者、分散式、實時或通用。
除了最高設計層外,需求可能很難說清。不過,需求可分為兩個基本大類:
使用者目標(user goal)和
系統目標(system goal)。
使用者要求系統具有一定的優良效能:系統該便於使用、易於學習和使用、可靠、安全和快速。當然,這些規範對於系統設計並不特別有用,因為如何實現這些沒有定論。
研發人員為設計、建立、維護和執行作業系統,也可定義一組相似要求:作業系統應易於設計、實現和維護,也應靈活、可靠、正確且高效。同樣,這些要求在系統設計時並不明確,並可能有不同的理解。
總之,關於定義作業系統的需求,沒有唯一的解決方案。現實中,存在許多型別的系統,這也說明了不同需求會產生不同解決方案,以便用於不同環境。例如,VxWorks(一種用於嵌入式系統的實時作業系統)的需求與 MVS(用於 IBM 大型電腦的多使用者、多存取作業系統)的需求相比,有很大不同。
作業系統的分析與設計是個很有創意的工作。雖然沒有教科書能夠告訴我們如何做,但是軟體工程(software engineering)的主要原則還是有用的。現在就來討論這些。
機制與策略
一個重要原則是策略(policy)與機制(mechanism)的分離。
機制決定如何做,而策略決定做什麼。例如,定時器是一種保護 CPU 的機制,但是為某個特定使用者應將定時器設定成多長時間,就是一個策略問題。
對於靈活性,策略與機制的分離至關重要。策略可隨時間或地點而改變。在最壞情況下,每次策略的改變都可能需要改變底層機制。對策略改變不敏感的通用機制將是更可取的。這樣策略的改變只需重新定義一些系統引數。
例如,現有一種機制,可賦予某些型別的程式相對更高的優先順序。如果這種機制能與策略分離開,那麼它可用於支援 I/O 密集型程式應比 CPU 密集型程式具有更高優先順序的策略,或者支援相反策略。
微核心作業系統(後續章節會詳細介紹)通過實現一組基本且簡單的模組,將機制與策略的分離用到了極致。這些模組幾乎與策略無關,通過使用者建立的核心模組或使用者程式本身,可以增加更高階的機制與策略。
例如,看一下 UNIX 的發展。起初,它採用分時排程。而對最新版的 Solaris,排程由可載入表來控制。根據當前的載入表,系統可以是分時的、批次處理的、實時的、公平分享的或其他任意組合。通用排程機制可以通過單個 load-new-table 命令對策略進行重大改變。
另一極端系統是 Windows,它的機制與策略都已編碼,以確保統一的系統風格。所有應用程式都有類似介面,因為介面本身已在核心和系統庫中構造了。Mac OS X 作業系統也有類似功能。
對於所有的資源分配,策略決定非常重要。只要決定是否分配資源,就應做出策略決定。只要問題是“如何做”而不是“做什麼”,就要由機制來決定。
實現
在作業系統被設計之後,就應加以實現。作業系統由許多程式組成,且由許多人員在較長時間內共同編寫,因此關於實現很難形成通用原則。
早期,作業系統是用組合語言編寫的。現在,雖然有的作業系統仍然用組合語言編寫,但是大多數都是用高階語言(如 C)或更高階的語言(如 C++)來編寫的。實際上,作業系統可用多種語言來編寫。核心的最低層可以採用組合語言。高層函數可用 C;系統程式可用 C 或 C++,也可用解釋型指令碼語言如 PERL 或 Python,還可用外殼指令碼。事實上,有的 Linux 發布可能包括所有這些語言編寫的程式。
首個不用組合語言編寫的系統可能是用於 Burroughs 計算機的主控程式(Master Control Program,MCP)。MCP 採用 ALGOL 語言的變種來編寫。MIT 開發的 MULTICS 主要是採用系統程式語言 PL/1 來編寫的。Linux 和 Windows 作業系統核心主要用 C 編寫,儘管有小部分是用組合語言來編寫的用於裝置驅動程式與儲存和恢復暫存器狀態的程式碼。
採用高階語言或至少系統實現語言來實現作業系統的優勢與用高階語言來編寫應用程式相同:程式碼編寫更快,更為緊湊,更容易理解和偵錯。另外,編譯技術的改進使得只要通過重新編譯,就可改善整個作業系統的生成程式碼。最後,如果用高階語言來編寫,作業系統更容易移植(port)到其他硬體。
例如,MS-DOS 是用 Intel 8088 組合語言編寫的。因此,它只能直接用於 Intel X86 型別的 CPU。(注意,雖說 MS-DOS 只能本地執行於 Intel X86 型別的 CPU,但是 X86 指令集模擬器可允許它執行在其他 CPU 上——會更慢,會使用更多資源。正如前面所提到的,模擬器(emulator)程式可以在一個系統上複製另一個系統的功能。)而 Linux 作業系統主要是用 C 來編寫的,可用於多種不同 CPU,如 Intel X86、Oracle SPARC 和 IBM PowerPC 等。
採用高階語言實現作業系統的缺點僅僅在於速度的降低和儲存的增加。不過,這對當今的系統已不再是主要問題。雖然組合語言高手能編寫更快、更小的子程式,但是現代編譯器能對大程式進行複雜分析並採用高階優化技術生成優秀程式碼。現代處理器都有很深的流水線和很多功能塊,它們要比人類更容易處理複雜的依賴關係。
與其他系統一樣,作業系統的重大效能改善很可能是來源於更好的資料結構和演算法,而不是優秀的組合語言程式碼。另外,雖然作業系統很大,但是只有小部分程式碼對高效能是關鍵的;中斷處理器、I/O管理器、記憶體管理器及CPU排程器等,可能是關鍵部分。在系統編寫完並能正確工作後,可找出瓶頸程式,並用相應組合語言程式來替換。