了解Linux發展史的同學都知道,關于linux吵架史的一段佳話,就是關于內核設計思想之爭,這段故事在linus Tovalds的自傳中也有提到。我們都知道linux操作系統由Linus Tovalds模仿minix操作系統開發的。
雖然Linux是受MINIX啟發而發明,但是在設計思想上采取了和原始UNIX一樣的宏內核的設計哲學,而不是MINIX采用的微內核的設計原則。
個人認為Linus Tovalds的偉大之處不在于他發明了Linux,而是他發明了Linux且在自由軟件之父Richard Stallman精神的影響下,把Linux開源了,成為開源領域的代表。
在Linux發展之初,林納斯和安德魯于1992年在新聞組上有過一場精彩的理念爭論。Minix的作者和支持者認為Linux的宏內核構造是“向七十年代的大倒退”,而Linux的支持者認為Minix本身沒有實用性。
這場吵架從1992年1月29日, 一直吵到1992年2月10日。帖子的導火索是安德魯教授發的一個帖子,名字為Linux已經過時了。帖子在1992年2月10日,一個叫尼爾斯的管理員受不了了,然后開了一個新的論壇給linux。從此Minix和Linux,大路朝天,各走一邊。 由于當時參與討論的好多大牛,包括Unix和創始人肯•湯姆森和日后成為Linux內核的二號人物大衛•米勒,還有幾個開發BSD內核的人,使這場討論成為Linux發展史上的佳話。
那究竟什么是微內核的設計原則?什么是宏內核的設計思想?
微內核(Microkernelkernel)
微內核的功能被劃分為獨立的過程,每個過程叫做一個服務器。理想情況下,只有強烈請求特權服務的服務器才運行在特權模式下,其他服務器都運行在用戶空間。不過,所有的服務器都保持獨立并運行在各自的地址空間。因此,就不可能像單模塊內核那樣直接調用函數,而是通過消息傳遞處理微內核通信:系統采用了進程間通信(IPC)機制,因此,各種服務器之間通過IPC機制互通消息,互換“服務”。服務器的各自獨立有效地避免了一個服務器的失效禍及另一個。
同樣,模塊化的系統允許一個服務器為了另一個服務器而換出。因為IPC機制的開銷比函數調用多,又因為會涉及內核空間到用戶空間的上下文切換,因此,消息傳遞需要一定的周期,而宏內核中簡單的函數調用沒有這些開銷。基于此,付之于實際的微內核系統讓大部分或全部服務器位于內核,這樣,就可以直接調用函數,消除頻繁的上下文切換。Windows NT內核和Mach(Mac OS X的組成部分)是微內核的典型實例。不管是Windows NT還是MacOS X,都在其新近版本中不讓任何微內核服務器運行在用戶空間,這違背了微內核設計的初衷。
在這些設計中,微內核部分經常只但是是個消息轉發站:當系統調用模塊要給文檔系統模塊發送消息時,消息直接通過內核轉發。這種方式有助于實現模塊間的隔離。(某些時候,模塊也能夠直接給其他模塊傳遞消息。)在一些微內核的設計中,更多的功能,如I/O等,也都被封裝在內核中了。但是根本的思想還是要保持微內核盡量小,這樣只需要把微內核本身進行移植就能夠完成將整個內核移植到新的平臺上。其他模塊都只依賴于微內核或其他模塊,并不直接直接依賴硬件。
微內核設計的一個長處是在不影響系統其他部分的情況下,用更高效的實現代替現有文檔系統模塊的工作將會更加容易。我們甚至能夠在系統運行時將研發出的新系統模塊或需要替換現有模塊的模塊直接而且迅速的加入系統。另外一個長處是無需的模塊將不會被加載到內存中,因此微內核就能夠更有效的利用內存。
宏內核(Monolithic kernel)
宏內核是兩大陣營中一種較為簡單的設計,在1980年之前,所有的內核都設計成宏內核。所謂宏內核就是把它從整體上作為一個單獨的大過程來實現,并同時運行在一個單獨的地址空間。因此,這樣的內核通常以單個靜態二進制文件的形式存放于磁盤。所有內核服務都在這樣的一個大內核空間中運行。內核之間的通信是微不足道的,因為大家都運行在內核態,并身處同一地址空間:內核可以直接調用函數,這與用戶空間沒有什么區別。這種模式的支持者認為單模塊具有簡單和高性能的特點。大多數Unix系統都設計為單模塊。
宏內核的內部又能夠被分為若干模塊(或是層次或其他),但是在運行的時候,他是個單獨的二進制大映象。其模塊間的通訊是通過直接調用其他模塊中的函數實現的,而不是消息傳遞。
宏內核的支持者聲稱微內核的消息傳遞開銷引起了效率的損失。微內核的支持者則認為因此而增加的內核設計的靈活性和可維護性能夠彌補任何損失。
為什么Linux必然是宏內核的呢?一個方面是歷史的原因:在Linus的觀點看來,通過把內核以單一的方式進行組織并在初始的空間中運行是相當容易的事情。這種決策避免了有關消息傳遞體系結構,計算模塊裝載方式等方面的相關工作。(內核模塊系統在隨后的幾年中又進行了不斷地改進。)
另外一個原因是充足的研發時間的結果。Linux既沒有研發時間的限制,也沒有深受市場壓力的發行進度。
任何的限制只有并但是分的對內核的修改和擴充。內核的單一設計在內部實現了充分的模塊化,在這種條件下的修改或增加都并不怎么困難。而且問題還在于沒有必要為了追求尚未證實的可維護性的微小增長而重寫Linux的內核。(Linus曾多次特別強調了如下的觀點:為了這點利益而損耗速度是不值得的。)
假如Linux是純微內核設計,那么向其他體系結構上的移植將會比較容易。實際上,有一些微內核,如Mach微內核,就已成功的證實了這種可移植性的長處。實際的情況是,Linux內核的移植雖然不是很簡單,但也絕不是不可能的:大約的數字是,向一個全新的體系結構上的典型的移植工作需要30,000到60,000行代碼,再加上不到20,000行的驅動程式代碼。(并不是任何的移植都需要新的驅動程式代碼。)粗略的計算一下,我估計一個典型的移植平均需要50,000行代碼。這對于一個程式員或多一個程式小組來說是力所能及的,能夠在一年之內完成。雖然這比微內核的移植需要更多的代碼,但是Linux的支持者將會提出,這樣的Linux內核移植版本比微內核更能夠有效的利用底層硬件,因而移植過程中的額外工作是能夠從系統性能的提高上得到補償的。
這種特別設計的權衡也不是很輕松就能夠達到的,宏內核的實現策略公然違背了傳統的看法,后者認為微內核是未來發展的趨勢。但是由于單一模式(大部分情況下)在Linux中運行狀態良好,而且內核移植相對來說比較困難,但沒有明顯地阻礙程式員團體的工作,他們已熱情高漲地把內核成功的移植到了現存的大部分實際系統中,更不用說類似掌上型電腦的一些看起來很不實際的目標了。只要Linux的眾多特點仍然值得移植,新的移植版本就會不斷涌現。
很有趣的一點是,這種爭論經常會令人想到前幾年CPU領域中RISC和CISC的斗爭。現代的成功CPU設計中包含了任何這兩種技術,就像linux內核是微內核和單一內核的混合產物相同。Linux內核基本上是單一的,但是他并不是個純粹的集成內核。
內核模塊系統將微內核的許多長處引入到Linux的宏內核設計中。
Linux是一個宏內核,也就是說,Linux內核運行在單獨的內核地址空間。不過,Linux汲取了微內核的精華:其引以為豪的是模塊化設計、搶占式內核、支持內核線程以及動態裝載內核模塊的能力。不僅如此,Linux還避其微內核設計上性能損失的缺陷,讓所有事情都運行在內核態,直接調用函數,無需消息傳遞。至今,Linux是模塊化的、多線程的以及內核本身可調度的操作系統。實用主義再次占了上風。
當Linus和其他內核開發者設計Linux內核時,他們并沒有完全徹底地與Unix訣別。他們充分地認識到,不能忽視Unix的底蘊(特別是Unix的API)。而由于Linux并沒有基于某種特定的Unix,Linus和他的伙伴們對每個特定的問題都可以選擇已知理想的解決方案——在有些時候,當然也可以創造一些新的方案。以下是對Linux內核與Unix各種變體的內核特點所作的分析比較:
•Linux支持動態加載內核模塊。盡管Linux內核也是宏內核,可是允許在需要的時候動態地卸除和加載部分內核代碼。
•Linux支持對稱多處理(SMP)機制,盡管許多Unix的變體也支持SMP,但傳統的Unix并不支持這種機制。
•Linux內核可以搶占(preemptive)。與傳統的Unix不同,Linux內核具有允許在內核運行的任務優先執行的能力。在其他各種Unix產品中,只有Solaris和IRIX支持搶占,但是大多數傳統的Unix內核不支持搶占。
•Linux對線程支持的實現比較有意思:內核并不區分線程和其他的一般進程。對于內核來說,所有的進程都一樣—只不過其中的一些共享資源而已。
•Linux提供具有設備類的面向對象的設備模型、熱插拔事件,以及用戶空間的設備文件系統(sysfs)。
•Linux忽略了一些被認為是設計得很拙劣的Unix特性,像STREAMS,它還忽略了那些實際上已經根本不會使用的過時標準。
•Linux體現了自由這個詞的精髓。
現有的Linux特性集就是Linux公開開發模型自由發展的結果。如果一個特性沒有任何價值或者創意很差,沒有任何人會被迫去實現它。相反的,在Linux的發展過程中已經形成了一種值得稱贊的務實態度:任何改變都要針對現實中確實存在的問題,經過完善的設計并有正確簡潔的實現。于是,許多其他現代Unix系統包含的特性,如內核換頁機制,都被毫不遲疑的引入進來。
現狀
除了QNX和基于Mach的UNIX等個別系統外,幾乎全部采用宏內核結構,例如大部分的Unix、Linux,以及Windows(微軟聲稱Windows NT是基于改良的微內核架構的,盡管理論界對此存有異議)。
作為微內核代表的GNU/Hurd的緩慢的發展現狀,似乎也在告訴我們微內核的優勢是學術理論的結果,而不是從實際應用得出的經驗。當然和HURD本身的發展計劃及開發模式也有一定關系,事實上以Hurd為代表的微內核的設計思想,其理論上的先進性并沒有真正的轉化為生產力。
Linux和HURD的現狀說明了只有經歷市場檢驗的技術才具有真正的生命力,就像1995年才推出的JAVA語言,因為其順應了INTERNET編程的需要,現在已經是主流網絡編程語言之,誕生于70年代的C語言,現在活力依舊。
Linux的蓬勃發展,似乎說明技術實現上相對簡單的操作系統更具有強勁的生命力,而隨著Linux不斷汲取了微內核的設計思想說明其并沒有局限于原有的設計思想,其在實用性層面又一次走在了前面。