聊了聊宏內(nèi)核和微內(nèi)核,并吹了一波 Linux
內(nèi)核是操作系統(tǒng)非常重要的組成部分,同時(shí)也是操作系統(tǒng)的核心。內(nèi)核管理著系統(tǒng)資源,內(nèi)核向上連接著應(yīng)用程序,向下連接著硬件,它是應(yīng)用程序和硬件的橋梁。
內(nèi)核可以進(jìn)一步的劃分,分為宏內(nèi)核和微內(nèi)核。
宏內(nèi)核和微內(nèi)核最大的區(qū)別就是,宏內(nèi)核的用戶服務(wù)和內(nèi)核服務(wù)都保存在相同的地址空間中,它們都由內(nèi)核進(jìn)行統(tǒng)一管理,而微內(nèi)核的用戶服務(wù)和內(nèi)核服務(wù)會保存在不同的地址空間中,下圖可以很好的解釋這一點(diǎn)。
其實(shí)這里的宏內(nèi)核翻譯過來有點(diǎn)牽強(qiáng),其實(shí)應(yīng)該叫單內(nèi)核或者單核。在這種單核的設(shè)計(jì)中,內(nèi)核是一個(gè)大的整體,可以說是一個(gè)大進(jìn)程,在這個(gè)大進(jìn)程中,所有內(nèi)核服務(wù)都運(yùn)行在一個(gè)地址空間中,函數(shù)之間的調(diào)用鏈路少,直接通信簡單高效。
而微內(nèi)核的功能會劃分為獨(dú)立的進(jìn)程,進(jìn)程之間通過 IPC 進(jìn)行通信,高度模塊化,一個(gè)服務(wù)的故障不會影響另一個(gè)服務(wù)。不過由于模塊化的影響,函數(shù)之間調(diào)用鏈路偏長,進(jìn)程之間不會直接通信,而是通過內(nèi)核服務(wù)相互通信。
從內(nèi)核大小上面來講,微內(nèi)核的尺寸更小,只包含用戶進(jìn)程相關(guān)的服務(wù),而單核的尺寸要比微內(nèi)核大的多,這點(diǎn)比較好理解,因?yàn)楹陜?nèi)核融入了太多服務(wù)和驅(qū)動。
從執(zhí)行效率上來說,微內(nèi)核的執(zhí)行效率相對較慢,因?yàn)樯婕暗娇缒K調(diào)用,而宏內(nèi)核執(zhí)行效率高,因?yàn)楹瘮?shù)之間會直接調(diào)用。
在微內(nèi)核模塊化之后,它很容易擴(kuò)展,因?yàn)閮?nèi)核空間與用戶空間相互隔離,在用戶態(tài)下(運(yùn)行在用戶空間中的應(yīng)用程序)應(yīng)用程序崩潰后一般不會影響到內(nèi)核中的數(shù)據(jù)。宏內(nèi)核的可拓展性較差。
經(jīng)過上面這些描述之后,我們很容易把宏內(nèi)核和微內(nèi)核的特征想象成軟件開發(fā)中的單體架構(gòu)和微服務(wù)架構(gòu)。
單體架構(gòu)最大的特點(diǎn)就是函數(shù)調(diào)用方便,幾乎不存在調(diào)用鏈路,一個(gè)項(xiàng)目解決所有問題,項(xiàng)目中包含數(shù)據(jù)庫驅(qū)動、各種攔截器、控制器、權(quán)限控制,可拓展性非常差。
而微服務(wù)的架構(gòu)之間的調(diào)用鏈路會比較長,模塊之間的職責(zé)分離并且相互依賴,比如權(quán)限控制模塊、路由模塊、總線通信模塊。可拓展性比較強(qiáng)。
這兩種不同的內(nèi)核結(jié)構(gòu)有不同的支持者,就和有些人認(rèn)為單體架構(gòu)好,有些人認(rèn)為微服務(wù)架構(gòu)模式好。
這就像對編程語言的爭論一樣,你說 Python 、Go、Java 以及其他語言哪個(gè)好?管他哪個(gè)好,最終都會戲謔的稱 PHP 是這個(gè)世界上最好的語言。所以,這些爭論本沒有意義,但是很有趣的是,這種爭論常常讓人想起前幾年在 CPU 領(lǐng)域中 RISC 和 CISC 之間的斗爭。
現(xiàn)代成功的 CPU 設(shè)計(jì)包括這兩種技術(shù)中的任何一種,就像 Linux 內(nèi)核是微內(nèi)核和宏內(nèi)核的混合產(chǎn)品一樣??赡苡行┤苏J(rèn)為 Linux 它不就是個(gè)宏內(nèi)核結(jié)構(gòu)么,但實(shí)際上 Linux 不單單只是一個(gè)純碎的集成內(nèi)核。
為什么 Linux 會使用單內(nèi)核(此處叫單內(nèi)核有點(diǎn)應(yīng)景)結(jié)構(gòu)呢?我猜有下面幾個(gè)因素。
從 Linus 的角度來看,單內(nèi)核的開發(fā)和選型更容易,因?yàn)楸苊饬伺c消息傳遞架構(gòu)、計(jì)算模塊加載方法等相關(guān)的工作。而且 Linux 的誕生原因在于 Linus 對 MINIX(一種類 UNIX 操作系統(tǒng))只允許在教育上使用很不滿,再加上 Linus 本來對操作系統(tǒng)很感興趣,于是他開始編寫 Linux 操作系統(tǒng),所以我認(rèn)為當(dāng)時(shí)的 Linus 開發(fā) Linux 起源于興趣,并未經(jīng)過詳細(xì)周到的設(shè)計(jì),也并未考慮它的可拓展性。當(dāng)然這只是鄙人粗淺的猜測。
這就和我們上大學(xué)的畢業(yè)設(shè)計(jì)一樣,你畢業(yè)設(shè)計(jì)做的系統(tǒng),你會考慮可拓展性嗎?除非你想當(dāng)產(chǎn)品來做,但是何必呢?
另一個(gè)原因是充足的開發(fā)時(shí)間。Linux 沒有研發(fā)時(shí)間限制,也沒有發(fā)布時(shí)間表。任何限制都只能單獨(dú)修改和擴(kuò)展內(nèi)核。核心的單一設(shè)計(jì)內(nèi)部完全模塊化,在這種情況下修改或添加不是很困難。問題是沒有必要為了追求未經(jīng)證實(shí)的可維護(hù)性的小幅增加而重寫 Linux 內(nèi)核。Linus 一再強(qiáng)調(diào)以下觀點(diǎn):為了這個(gè)好處而損失速度是不值得的。
Linux 是一個(gè)借鑒了微內(nèi)核精髓的宏內(nèi)核結(jié)構(gòu),Linux 支持模塊化的設(shè)計(jì)、搶占式內(nèi)核、對內(nèi)核線程的支持以及動態(tài)加載內(nèi)核模塊的能力。不僅如此,Linux 還避免了其微內(nèi)核設(shè)計(jì)的性能損失,允許一切運(yùn)行在內(nèi)核模式下,直接調(diào)用函數(shù),無需消息傳遞。
所以綜合一點(diǎn)來講,Linux 是一個(gè)模塊化、多線程和內(nèi)核可調(diào)度的操作系統(tǒng)。
模塊化的設(shè)計(jì):Linux 支持內(nèi)核模塊的動態(tài)加載,盡管 Linux 內(nèi)核也是單核,但它允許在需要時(shí)動態(tài)刪除和加載一些內(nèi)核代碼。
可搶占性:Linux 內(nèi)核支持可搶占,與傳統(tǒng)的 UNIX 不同,Linux 內(nèi)核具有允許內(nèi)核中運(yùn)行的任務(wù)優(yōu)先執(zhí)行的能力。在各種 UNIX 產(chǎn)品中,只有 Solaris 和 IRIX 支持搶占,但大多數(shù)傳統(tǒng) UNIX 內(nèi)核不支持搶占。
在 Linux 身上,完美體現(xiàn)了務(wù)實(shí)性。如果一項(xiàng)功能沒有價(jià)值或創(chuàng)意不佳,則不會開始實(shí)施。相反,在 Linux 的發(fā)展過程中,形成了一種值得稱道的務(wù)實(shí)態(tài)度:任何改變都必須針對現(xiàn)實(shí)中實(shí)際存在的問題,需要經(jīng)過完整的設(shè)計(jì)和正確簡潔的實(shí)現(xiàn)。
如果 Linux 是純微內(nèi)核設(shè)計(jì),那么移植到其他架構(gòu)會更容易。實(shí)際情況是,Linux 內(nèi)核移植雖然不是很簡單,但也絕非不可能完成的事情。