Linux 為什麼還要堅持使用宏內核?

目前主流的操作系統(MAC OS X,Windows)都是使用了微內核來實現,但是 Linux 卻仍然堅持使用宏內核架構。


作為一個在System方向實驗室待過的同學來稍微補充一下這個問題的答案。

@馮東@王垠 的答案更多是從Monolithic Kernel和Micro Kernel的設計角度比較優劣,這個話題爭論的時間比較久,也需要蠻長篇幅來說。就本問題來說,「Linux為什麼堅持使用Monolithic Kernel」和設計優劣還是有一定區別的。

@詹健宇 的回答與本主題較為貼近,Linus Torvalds與Andrew S. Tanenbaum(當時System研究領域的大牛 Modern Operating System一書的作者,也是今天System界領軍人物Frans Kaashoek的老師)有過一場關於Linux設計是否過時的爭論(https://groups.google.com/forum/#!topic/comp.os.minix/wlhw16QWltI%5B1-25-false%5D),當時學術界主流觀點是Monolithic Kernel只有在效率上相對Micro Kernel有優勢,並且已經有學者的研究結果表明Micro Kernel的效率經過優化並不比Monolithic Kernel差。從設計角度,當年Linus在討論中也一定程度上同意了這個觀點。

那麼為什麼Linus還是採用Monolithic Kernel作為Linux的設計模型呢?首先,Linux本身在實現之初僅僅作為Linus一個業餘項目而存在。而Monolithic Kernel由於不需要處理消息隊列等等原因從實現角度來說比Micro Kernel更為方便,我個人認為這是Linus採用Monolithic Kernel的原因之一。其他原因可能是他本人從情感上喜歡這一架構,也可能他順延模仿的Unix或者認為現有Micro Kernel消息傳遞的實現代碼很ugly。但這些原因並不是重點,重點在於他的作品與採用Micro Kernel的Minix相比,它的易用性更好。

Minix為了儘可能兼容更多的硬體設備,做到更加全面的兼容性,在實現上盡量避免利用單一某種處理器的新特性,這也是導致其效率不高的原因之一。而Linux則認為操作系統只需要對用戶態程序保持統一的API即可保證兼容性,底層硬體的驅動等支持可以擴充,並且工作量不大。在編寫Linux的開始階段,僅支持在當時使用人數占多數的i386架構,但在內存管理,網路等模塊上實現均優於Minix,因此取得了大量用戶的支持,並最終流行。

回到這個問題,Linux保持Monolithic Kernel設計的原因是,Linux在這種架構上可以實現的足夠好(現在的Linux Kernel也證明了這一點),即使費很大力氣切換到Micro Kernel架構並不會獲得什麼優勢。同時,這些不代表Micro Kernel從今天的角度來看設計就劣於Monolithic Kernel。通過種種途徑的優化總可以變得完善。Nokia的Symbian系統也統治了一段時間。所以歸根到底,決定一款產品是否成功的要素不僅僅取決於它的設計,也在於它的實現。很有意思的是,計算機領域往往經過完善設計的產品最終結果都是失敗了,像UNIX贏了Multics,設計很好的Lisp並沒有C語言流行, 又像同設計OSI的願景最後由TCP/IP協議完成。這篇Worse is Better就是說的這個道理:Worse Is Better

另外@王垠可能對System領域了解不是很深:) 操作系統保護內存的原因並不是因為C語言的限制。操作系統設計的目的是為了方便用戶態程序不用過於關心硬體的底層細節,為用戶態程序提供各種系統資源的抽象。而內存隔離的目的一是為了用戶態程序不影響其他用戶態程序的狀態,二是為了操作系統本身的安全性,狀態不被用戶態程序所修改。而C語言的指針操作只是對內存訪問的一種直接描述罷了,並不是C語言影響了操作系統或者處理器的設計。其他動態類型檢查的比較,由於我對程序語言領域沒有很多了解,所以沒有辦法評論。最後補充一下宏內核的宏的意思是大,即將內存管理,文件系統等模塊均置於內核態,所以是Monolithic,而不是Macro這個宏:)


首先,linus 這人對微內核不感冒,這個大家都知道,他在一天,kernel就不會考慮微內核化。
另外,linux kernel在發展過程中,形成了自己的工程方法論,註定無法向微內核方向演化。
kernel 重視更動,強調不斷翻新,輕視特徵和實現的穩定性. 例如,沒有固定的api,甚至源代碼級的固定api也不允許存在。內核內部子系統介面變動是家常便飯。提倡廠商將驅動合入內核以便於跟上變動,跟不上變動的子系統和驅動被kernel維護者拋棄被認為是很正常的。想想看,如果子系統必須要隨著同版本的整個系統一起編譯,誰還願意設計成分離地址空間和通過ipc 通訊的工作模式。
總的說來,kernel 開發的思想是將軟體系統看做動態變化的生物,而非完美設計的機器。爭取通過日常工作流程,自然地發現問題,清理陳痾。微內核思想來自學術界,想像的操作系統各部分能夠分隔清楚,介面定義良好,這和獲得很大成功的kernel實踐經驗格格不入。
最後,linux kernel 很成功,沒有改變基本模式的動力。


這個答案那麼久了以後,好多人還來點贊真是太感謝了啊。終於周末了我來補充一下這個答案吧。

首先先說說操作系統是幹什麼的吧。如果專業是計算機的同學可能學過操作系統這門課程,會發現課程上講的內容和我們所認識到的操作系統差別很大。這個裡面所講的正是操作系統最核心的功能,任務調度、內存和設備的抽象和管理。然後 ,為了我們方便使用,才集成進了系統服務、驅動程序、文件系統之類的東西。

我們平時運行的程序,每個程序各運行幾十毫秒,大家來回輪換,這樣子我們看起來這些程序好像在「同時」運行一樣。應用程序之所以能夠被操作系統通過時間片的方式調度,是因為對於CPU而言,普通的應用程序和操作系統的內核運行在不同的特權級別上,我們叫作rings。應用程序運行在Ring 3,而內核運行在Ring 0。

隨著科技的發展,操作系統變得越來越複雜,內核裡面的東西也越來越多。人們也就開始考慮是否應該改變原有的架構,從而提高操作系統的性能和穩定性,主要是精簡內核降低開發的複雜度,還有就是把各種程序儘可能的隔離,保證一個程序的崩潰不會牽連到其他的程序。上世紀80年代人們討論得火熱的微內核就是這樣一種架構。

微內核考慮在操作系統的內核中保留操作系統最基本的功能,也就是任務調度、內存和設備的抽象和管理。其他的功能全部從內核移出,放到用戶態中了實現,並以C/S模式對其他應用程序提供服務。

微內核帶來的好處主要是穩定性和實時性,即內核中模塊數量少了,結構更精簡更優化了,能夠影響內核的程序和驅動也減少了,穩定性隨之提高;另外就是實時性,內核精簡了以後,響應的時延的減小。不過並不是精簡了以後會使得性能提升,微內核使得內核中只有最關鍵的部分,其他模塊和系統功能全部作為獨立模塊放到用戶態空間中運行,功能分散了以後增加了通信的成本。不過微內核操作系統的特點尤其適合工控系統的控制,而且設計簡單,在小型的系統中有不少的應用。另外亦有不少實時操作系統是使用微內核架構設計。


所有的理論設計,放到現實的工程中都是要做折衷的。所以有混合內核的出現,綜合宏內核和微內核的不同優點,在兩個方案中折衷設計。OS X和Windows就屬於這類。至於Linux,上千萬行代碼,架構豈是說改就能改的。使用Linux構建的系統,不少都是要追求性能的吧,前面也說到微內核會降低性能,在Linux中,我們為了使得一個事情性能更高,往往還要把這個模塊放到內核中運行,比如PF_RING。所以在需要考慮性能的時候,微內核又顯得不那麼合適,像微軟一樣取一個折衷算是一個好的辦法。

----分割線以下是原來的回答----
誰告訴你Mac OS X和Windows是微內核的?


其實所有的理論上完美的問題在實踐過程中都會遇到各種不得不妥協的折衷.因為你製造出的東西是要部署到實際生活生產環境中使用的. 不是要一個只在實驗室中看起來很完美的作品. 微內核的高度模塊化,自然要付出成本的,那就是增加代碼交互的冗餘與效率的損耗, 而這恰恰是很大的問題.

P.S. 建議你看看Linus在剛發布Linux後不久與Tanenbaum的一場關於linux為何不使用microkernel的著名的爭論:http://en.wikipedia.org/wiki/Tanenbaum%E2%80%93Torvalds_debate
這次著名的口水仗中, 展現了工程派代表[1]及典型學院派老學究[2]之間的分歧,很有代表性, 值得一讀.

[1] 從Linus本人的作品與平時在Linux郵件列表上的發言來看,他是一名實用主義者,他說過句名言: Talk is cheap. Show me the code. (https://lkml.org/lkml/2000/8/25/132)
[2] Tanenbaum開發了Minix這個微內核的unix-like操作系統, 這就是一個純為教學而開發的系統, 它是代表學院派理念性的作品


這問題下面已經被大神佔領了~我這個小蝦米也斗膽發表一下意見。

操作系統內核可能是微內核,也可能是單內核(後者有時稱之為宏內核Macrokernel)。按照類似封裝的形式,這些術語定義如下:
微內核(Microkernelkernel)――在微內核中,大部分內核都作為單獨的進程在特權狀態下運行,他們通過消息傳遞進行通訊。在典型情況下,每個概念模塊都有一個進程。因此,假如在設計中有一個系統調用模塊,那麼就必然有一個相應的進程來接收系統調用,並和能夠執行系統調用的其他進程(或模塊)通訊以完成所需任務。
在這些設計中,微內核部分經常只但是是個消息轉發站:當系統調用模塊要給文檔系統模塊發送消息時,消息直接通過內核轉發。這種方式有助於實現模塊間的隔離。(某些時候,模塊也能夠直接給其他模塊傳遞消息。)在一些微內核的設計中,更多的功能,如I/O等,也都被封裝在內核中了。但是最根本的思想還是要保持微內核盡量小,這樣只需要把微內核本身進行移植就能夠完成將整個內核移植到新的平台上。其他模塊都只依賴於微內核或其他模塊,並不直接直接依賴硬體。
微內核設計的一個長處是在不影響系統其他部分的情況下,用更高效的實現代替現有文檔系統模塊的工作將會更加容易。我們甚至能夠在系統運行時將研發出的新系統模塊或需要替換現有模塊的模塊直接而且迅速的加入系統。另外一個長處是無需的模塊將不會被載入到內存中,因此微內核就能夠更有效的利用內存。
單內核(Monolithic kernel)――單內核是個很大的進程。他的內部又能夠被分為若干模塊(或是層次或其他)。但是在運行的時候,他是個單獨的二進位大映象。其模塊間的通訊是通過直接調用其他模塊中的函數實現的,而不是消息傳遞。
單內核的支持者聲稱微內核的消息傳遞開銷引起了效率的損失。微內核的支持者則認為因此而增加的內核設計的靈活性和可維護性能夠彌補任何損失。
我並不想討論這些問題,但必須說明很有趣的一點是,這種爭論經常會令人想到前幾年CPU領域中RISC和CISC的鬥爭。現代的成功CPU設計中包含了任何這兩種技術,就像Linux內核是微內核和單一內核的混合產物相同。Linux內核基本上是單一的,但是他並不是個純粹的集成內核。內核模塊系統將微內核的許多長處引入到Linux的單內核設計中。(順便提一下,我考慮過一種有趣的情況,就是Linux的內核模塊系統能夠將系統內核轉化成為簡單的不傳遞消息的微內核設計。雖然我並不贊成,但是他仍然是個有趣的想法。)

單內核與微內核設計之比較

操作系統內核可以分為兩大設計陣營:單內核和微內核(第三陣營外內核,主要用在科研系統中,但也逐漸在現實世界中壯大起來)。

單內核是兩大陣營中一種較為簡單的設計,在1980年之前,所有的內核都設計成單內核。所謂單內核就是把它從整體上作為一個單獨的大過程來實現,並同時運行在一個單獨的地址空間。因此,這樣的內核通常以單個靜態二進位文件的形式存放於磁碟。所有內核服務都在這樣的一個大內核空間中運行。內核之間的通信是微不足道的,因為大家都運行在內核態,並身處同一地址空間:內核可以直接調用函數,這與用戶空間沒有什麼區別。這種模式的支持者認為單模塊具有簡單和高性能的特點。大多數Unix系統都設計為單模塊。

另一方面,微內核並不作為一個單獨的大過程來實現。相反,微內核的功能被劃分為獨立的過程,每個過程叫做一個伺服器。理想情況下,只有強烈請求特權服務的伺服器才運行在特權模式下,其他伺服器都運行在用戶空間。不過,所有的伺服器都保持獨立並運行在各自的地址空間。因此,就不可能像單模塊內核那樣直接調用函數,而是通過消息傳遞處理微內核通信:系統採用了進程間通信(IPC)機制,因此,各種伺服器之間通過IPC機制互通消息,互換「服務」。伺服器的各自獨立有效地避免了一個伺服器的失效禍及另一個。

同樣,模塊化的系統允許一個伺服器為了另一個伺服器而換出。因為IPC機制的開銷比函數調用多,又因為會涉及內核空間到用戶空間的上下文切換,因此,消息傳遞需要一定的周期,而單內核中簡單的函數調用沒有這些開銷。基於此,付之於實際的微內核系統讓大部分或全部伺服器位於內核,這樣,就可以直接調用函數,消除頻繁的上下文切換。Windows NT內核和Mach(Mac OS X的組成部分)是微內核的典型實例。不管是Windows NT還是MacOS X,都在其新近版本中不讓任何微內核伺服器運行在用戶空間,這違背了微內核設計的初衷。

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的發展過程中已經形成了一種值得稱讚的務實態度:任何改變都要針對現實中確實存在的問題,經過完善的設計並有正確簡潔的實現。

為什麼Linux必然是單內核的呢?

一個方面是歷史的原因:在Linus的觀點看來,通過把內核以單一的方式進行組織並在最初始的空間中運行是相當容易的事情。這種決策避免了有關消息傳遞體系結構,計算模塊裝載方式等方面的相關工作。(內核模塊系統在隨後的幾年中又進行了不斷地改進。)另外一個原因是充足的研發時間的結果。Linux既沒有研發時間的限制,也沒有深受市場壓力的發行進度。
任何的限制只有並但是分的對內核的修改和擴充。內核的單一設計在內部實現了充分的模塊化,在這種條件下的修改或增加都並不怎麼困難。而且問題還在於沒有必要為了追求尚未證實的可維護性的微小增長而重寫Linux的內核。(Linus曾多次特彆強調了如下的觀點:為了這點利益而損耗速度是不值得的。)
假如Linux是純微內核設計,那麼向其他體系結構上的移植將會比較容易。實際上,有一些微內核,如Mach微內核,就已成功的證實了這種可移植性的長處。實際的情況是,Linux內核的移植雖然不是很簡單,但也絕不是不可能的:大約的數字是,向一個全新的體系結構上的典型的移植工作需要30,000到60,000行代碼,再加上不到20,000行的驅動程式代碼。(並不是任何的移植都需要新的驅動程式代碼。)粗略的計算一下,我估計一個典型的移植平均需要50,000行代碼。這對於一個程式員或最多一個程式小組來說是力所能及的,能夠在一年之內完成。雖然這比微內核的移植需要更多的代碼,但是Linux的支持者將會提出,這樣的Linux內核移植版本比微內核更能夠有效的利用底層硬體,因而移植過程中的額外工作是能夠從系統性能的提高上得到補償的。
這種特別設計的權衡也不是很輕鬆就能夠達到的,單內核的實現策略公然違背了傳統的看法,後者認為微內核是未來發展的趨勢。但是由於單一模式(大部分情況下)在Linux中運行狀態良好,而且內核移植相對來說比較困難,但沒有明顯地阻礙程式員團體的工作,他們已熱情高漲地把內核成功的移植到了現存的大部分實際系統中,更不用說類似掌上型電腦的一些看起來很不實際的目標了。只要Linux的眾多特點仍然值得移植,新的移植版本就會不斷湧現。


目前得票第二的 @王垠 的答案比較有誤導性。所以說明一下。

Micro-kernel 和 kernel 的「動態性」無關。實際上,Linux kernel 內部有大量的動態行為。包括動態地使用文件系統 driver,動態載入 module。只要這些動態行為都發生在 kernel-space,就還是 monolithic-kernel。所以 @王垠 的基本比喻就是錯誤的。

用類似的比喻,Micro-kernel 的性能問題不在於「問這東西在哪」,而在於必須「把這東西複製一份,外加校驗」,從而防止內存 corruption 引起的 bug。

系統越大,bug 越多,這個事實不假。但是 micro-kernel 的擁躉搞錯了一件事情:bug 增長的拐點在什麼地方。在拐點之前,要用艱苦奮鬥修 bug 來解決,拐點之後,才需要加 defensive 機制。否則就是 over-defensive。什麼叫 over-defensive?如果你的代碼每次訪問一個指針都要檢查 nullity,不管是高層模塊還是底層模塊,就是 over-defensive。Over-defensive 不光不能減少 bug,還會把一些在 sanity/smoking test 就能發現的 bug 整成 random failure。事實證明,Unix 內核根據「mechanism, not policy」制定的極為精簡的功能需求的複雜度遠遠在造成 bug 增長的拐點之前。

最後,monolithic-kernel 就是 micro-kernel。誰也不能阻止你把 Linux kernel driver 的 policy 部分挪到 user-space,甚至你可以把 Linux 的 paging policy 也寫成 demon。很多 Linux 的 CPU 中斷相應調度就是在 user-space 控制的。Micro-kernel 只是強制的 micro-kernel。


微內核提供了內核模塊之間更好的隔離(Isolation)方案,但是大大增加了通訊成本和協作的複雜度。所以兩害相權取其輕


基礎體系結構的東西,一旦選定了就沒辦法再改了,即使現在linux開發者們都後悔了也只能繼續堅持了。
再說,目前的架構不也運作得很好嗎?數以億計的linux設備都能正常工作,有些小困難也是可以克服的。
另外,我個人從工程實踐的角度看,目前linux宏內核結構是比較有開發效率的一種模式,尤其是在開源項目這種運作方式下。


個人覺得微內核和模塊化是兩碼事,但是很多人卻把他們混為一談。

微內核的最主要的特徵是操作系統組件之間的地址空間隔離,內核提供IPC,內存管理,任務調度的基本功能,其他的操作系統組件如文件系統,驅動程序等都在各自獨立的地址空間執行。一般來說應用程序調用操作系統的系統調用,或者內核調用其他組件(比如文件系統,驅動程序)的功能都是通過IPC的方式。

如果沒有這樣的特徵,那就不是微內核,如果只是模塊化,那麼我相信在微內核的概念出現之前,操作系統就是模塊化設計的了,畢竟模塊化的設計思想早在微內核之前就出現很久了。

基本上所有的操作系統都會有進程調度,內存管理,IO管理,文件系統,驅動程序等等諸如此類的模塊。

所以,從這個角度說Linux/Windows NT其實也是單一內核的。當然你要是說Windows NT是混合內核,勉強也可以,但是我認為Windows NT離單一內核更近一點。

而且Windows NT的圖形系統是運行在核心態的。而Linux的X Windows反倒是運行在用戶態的進程。

如果只是把一個不是特別重要的核心態驅動程序的實現移到用戶態運行就是微內核的話,那麼我相信Linux都可以做到(當然你還是需要一些運行在核心態的代碼做一些數據結構轉換或者消息轉發以實現對用戶態運行的驅動代碼的調用)。但是那應該不是微內核。


微內核企圖用獨立的進程,獨立的地址空間作為邊界來使系統變得更穩定,但是這樣的設計引入了新的問題:

其中之一就是性能,IPC的通訊方式帶來比單一內核更大的開銷,畢竟在進程間傳遞消息,無論怎麼優化也不可能比一個進程內的函數調用更有效率。更何況進入多核的時代,微內核基於IPC機制的操作系統組件間的通訊會導致更加頻繁的進程上下文切換,從而帶來更頻繁的cache失效。

其二就是微內核架構導致的操作系統組件間的通訊的複雜性,GNU/HURD的難產或多或少的證明了這一點。


就我看來,很多一開始宣稱是微內核的操作系統(Windows NT, OSX),其實很快就走上了去微內核的歷程。


因為Linus可以把這些亂七八糟的東西全都一個人寫了,一遍寫對了,還能穩定跑起來無bug,而我們這些渣渣做不到,只能依靠保護模式來防止幾百個工程師寫出來的那一坨垃圾動不動藍屏,自己弱卻去質疑天才的做法,和明知自己弱還要模仿天才的做法,都是認不清現實的表現。
=============================================================
工程這個東西是很有意思的,我們說科學是掌握規律,技術是利用規律克服大自然的限制,而工程,卻是利用技術來克服人自身的限制。技術會告訴你,造個金字塔,把石頭壘成四稜錐就行了,如果你是個力大無窮的巨人,或者是個能意念移物的魔法師,你就啪啪啪把石頭搬過來堆起來就完事了。但我們是凡人,我們力量很小,我們很弱,所以我們需要滾木,需要滑輪,需要繩索來幫忙,做了許多額外的麻煩事情,只為了克服我們肉體的自身限制。
體力上有限制,智力上同樣有限制。軟體工程很大程度上就是解決我們人類智力上限制的問題,軟體工程師在面對不知所謂的kernel dump的時候會無助,會哭泣,在面對無休止的介面變動的時候會歇斯底里,面對改一行代碼系統就全掛的窘境束手無策,所以我們需要微內核、微服務這樣的框架來約束系統,降低系統的複雜性,讓我們所有犯的錯誤都能保持在可控的範圍內,讓因為我們的愚笨而寫出的有bug的代碼也能勉勉強強運行起來而不是分分鐘crash,哪怕這些方法額外增加了許多工作量、還降低了效率。
但是,總是有超人存在的,我們人要造一個紀念碑,設計一堆方案,superman會說,哈?這個事情,不是只要我去把那個石頭舉起來,然後飛過來,放在這裡不就好了嘛?體力上差距這麼大的超人也許不存在,但智力上差距這麼大的超人卻是存在的,所以要記住工程方法只是為了拯救我們這些凡人,對於超人來說,他們是不需要這些的,他們要做的僅僅是「搬起來,放下去」而已。


本文還這個回答的一個債:Linux 戰略或生態圈是什麼? - in nek 的回答。裡面提到微內核都是學院派的意淫,這裡回答為什麼。

我沒有指向——我只是為了說明問題——如果是真心問這個問題很大程度上反映了提問者還是個代碼中二:)

我說的「中二」,是那種沒有經驗,只有「名」,沒有「實」的思考者。具體名稱空間定義參考這裡:《道德經》講了什麼?為什麼它廣受推崇? - in nek 的回答。這種人,在社會中是會被老子這樣的人K的:)

對應地,這樣的人在Linux世界中也是要被Linus K的。

我解釋一下為什麼:「是否微內核」僅僅是一個名字定義的問題,和用戶要解決的問題一點關係都沒有。我們在維護架構的時候,首先保證不創建額外的概念解決非直接用戶相關的問題。這種情況下,為什麼要為Linux引入微內核?現在沒有問題要解決了?到了吃飽飯沒事幹瞎做死的時候了嗎?

微內核只是學院概念,學院概念都是聽著很有道理,但經過打磨以後才能肯定是否正確道路的。你看每年有多少紅點設計獎?有幾個被複制到所有的類似產品中的?為什麼沒有複製?不是專利和版許可權制,是那個設計有創意,但並不實用。

微內核有成功的例子么?Minix是個教學系統,WindowsNT一開始說微內核,結果怎麼呢?把圖像渲染丟內核里了,QNX算是最成功的商用微內核系統了,但我告訴你QNX是怎麼工作的:你要把用戶程序,協議棧,驅動都放到一個進程中的。

這背後反映了什麼?這反映了,如果你要參與市場競爭,你要用盡一切能力去保證功能和性能,其他一切理論優勢,都是不靠譜的。微內核可以優化到和宏內核一樣的數據流效率嗎?如果它能夠,它就不是微內核了好吧?所以,你讓微內核系統如何在市場競爭中活下去?不能在市場競爭中活下去,誰來開發微內核系統?

而且,比如Linux這樣的架構,有什麼東西阻止你把驅動放到用戶態了嗎?(否則你以為fuse是什麼?)有什麼阻止你在其中增加一個優化的進程間通訊嗎?什麼都沒有。換言之,宏內核系統分分鐘可以變成微內核系統,而微內核系統是無法回頭的。

你要成為一個想Linus那樣的好架構師,真要好好學學這個基礎的虛心實腹的設計理念。這個理念現在貫穿所有的Linux核心維護者的維護哲學。比如他們基本上,不接受沒有硬體支持的代碼,不接受概念產品的代碼,不接受已經上市產品的代碼。這些都是這個基本理念的一脈相承。


目前大部分微內核都是一個渣渣(除了L4之類玩命的),而且微內核開發難度比較高(比如GNU Hurd,RMS自己也承認了)
別忘了托瓦茲是個追求效率的,好了。


多看點linux kernel的書,讀讀linux kernel源碼,然後就會覺得這個問題有些無謂...
主要基於以下考慮...

1. monolithic 是沒錯啦, 但是現在 linux kernel 正運行著的情況下支持動態載入/卸載模塊, 這意味著你可以(注意是在kernel正在運行著的情況下哦!)動態增減 kernel 的功能. 單這一點就使得微內核的吸引力大大減少了.

2. 內存管理文件系統進程調度IPC它們都是核心子系統/功能, 就是應該放一塊的, 何必非要把文件系統又單抽出來實現為一個服務進程什麼的. 別以為只是通訊消耗系統性能什麼的, 假設文件系統依賴某個驅動(實際上VFS層下最終也是要驅動的), 那那些個驅動又怎麼辦, 有那麼純潔的 VFS 進程什麼的嗎? 怕最終還不是要搞些亂七八糟的髒東西在裡面, 一個不小心搞得比宏內核更臟也不一定:)

3. 有了動態載入/卸載模塊的能力, 實際上你要把某些個子系統實現成模塊也可以的, 不過相對微內核來說linux這種實現讓那個載入的模塊或者子系統只能在特權級下面運行並且和內核共享地址虛擬地址空間(嗯內核當然也是用的虛擬地址, 就算32位系統normal zone直接映射那也是要轉換的)而已. 既然如此何必脫褲子放屁乾脆扔內核裡面得了(當然也是要足夠核心的子系統才這麼干, 也不是啥垃圾都往裡面扔).

4. linux的代碼組織還算良好,雖然對我這種菜B來說只是略懂皮毛,但畢竟目前還是可維護的^_^,而且實際上內核核心子系統的實現部分代碼演進/特性增強並不是像內核代碼增長速度那麼恐怖(那都是驅動啦!還有感謝ARM的亂七八糟). 雖然kernel的學習曲線確實是非常陡峭, 但只要勤奮點, 多看書, 多實踐, 終究還是能弄懂些東西的.

5. 別光顧著看這子系統那子系統什麼的, 抽空看看構建系統, linux內核怎麼被構建出來的? 說是宏內核, 不過這個單一二進位文件也不是隨便拼裝的哦, 是有講究的. 你把這拼裝的講究都整明白了, 說不定會覺得微內核那種理論上看上去妙的東西反而不咋地也不一定(宏內核也是有拼裝結構的嘛, 認真拼裝下也還是挺漂亮的吧 -- 哎呀你也是程序員啊那咱也別扯淡了就是說有空研究下kernel裡面的Makefile之類的腳本順便看看它怎麼鏈接的).

當然微內核在理論上和美學上仍然是有一些優勢的, linus本人也承認這一點. 也許未來linux kernel真沒辦法維護了的時候, 可能會再度認真考慮微內核的理論. 老實說linux kernel為了容納增加各種亂七八糟的特性確實有越來越臃腫的趨向. 比如容器, 就是內核Namespace, 現在被用做各種docker的基礎, 但這特么導致了kernel代碼的增加和一堆亂七八糟的數據結構, 我個人挺不喜歡的; 另外要吐槽的比如SELinux, 我覺得那玩意安全是安全, 就是特么各種配置文件亂七八糟難懂且不知所云(畢竟人一生的時間有限啊), 也要在內核裡面搞些莫名其妙的代碼.

ps: linux裡面一些成對使用的函數命名確實也真特么有點糟糕.

phew... 總體來說linux還是非常不錯的, 但肯定不是完美無缺的. 至於其它的微內核實現的kernel... 唉唉, 精力和智商都有限啊... 吐槽完畢.


印象中osx和windows都是混合內核


剛好在看Abraham Silberschatz等人寫的Operating System Concepts 9th這本書,從書上摘幾個圖片下來,希望能給您提供幫助。

關於微內核,原文引用如下:

One benefit of the microkernel approach is that it makes extending the operating system easier.
The performance of microkernels can suffer due to increased system-function overhead. Consider the history of Windows NT. The first release had a layered microkernel organization. This version』s performance was low compared with that of Windows 95.

Typical Microkernel Architecture

關於Unix等其他系統的架構原文引用如下:

Perhaps the best current methodology for operating-system design involves using loadable kernel modules. Here, the kernel has a set of core components and links in additional services via modules, either at boot time or during run time. This type of design is common in modern implementations of UNIX, such as Solaris, Linux, and Mac OS X, as well as Windows.

Unix architecture


Mac OS X architecture

這其中Mach就是典型的microkernel,

這其中Mach就是典型的microkernel,@狼大人 在評論中說Mac OS X是微內核想必指的是這個吧,再次引用書中原話

……
the kernel environment consists primarily of
the Mach microkernel and the BSD UNIX kernel. Mach provides memory management; support
for remote procedure calls (RPCs) and interprocess communication (IPC)
facilities, including message passing; and thread scheduling. The BSD component
provides a BSD command-line interface, support for networking and file systems,
and an implementation of POSIX APIs, including Pthreads.

Solaris architecture


書上似乎沒有給windows的architecture,從網上下了一個下來

本人新手,如有問題,非常歡迎各位前輩指正


Linux設計之初就是單體內核。後來沒有變是因為沒有變的必要。很多微內核的特性,其實Linux已經實現了。如果有一天,Linux由於單體內核的架構而無法適應某些重要的應用場景,那麼Linux社區一定會開發一個微內核kernel的。不要糾結於理論,理論是服務於實踐的


微內核性能不行,混合內核有點雞肋,宏內核是潮流。。。
osx的混合內核xnu內,是不得已而為的妥協方案;而且mach層的系統調用越來越少,只有機器性cpu、mem等純硬體相關的api;放在bsd層的系統調用越來越多,終有一天,xnu也會變成一個宏內核。


微內核:結構清晰,系統健壯

宏內核:開發容易,效率更高


因為Linux要確保他的可移植特性,對於性能不高的晶元,宏內核比微內核更高效,如果你在一個簡單的微控制器上實現一個操作系統,首先想到的就是宏內核,因為宏內核更高效,更容易實現!所以Linux採用宏內核是很自然的一種方式。


我想說,現在沒有絕對宏內核,也沒有絕對微內核,只是某種形式的雜種


推薦閱讀:

如何評價 2013 年款 Mac Pro?

TAG:Mac | 操作系統 | Linux | Linux 內核 | 操作系統內核 |