前面介紹的rCore操作系統(tǒng):rCore入門-來自清華的OS前沿教程,是清華的教學(xué)OS,相當(dāng)于使用Rust語言山寨了下Linux,是一個宏內(nèi)核。
之前我有一篇文章介紹了微內(nèi)核:seL4微內(nèi)核入門-微內(nèi)核介紹,相對來說微內(nèi)核在學(xué)術(shù)上更嚴謹先進一些,盡管性能不如宏內(nèi)核,其他方面有點多,特別是安全性。
所以清華又搞了一個zCore思路還是山寨,這次瞄上了谷歌Fuchsia的Zicron微內(nèi)核,見之前的文章Fuchsia入門-簡介和代碼介紹,總結(jié)下:
rCore:使用Rust語言山寨宏內(nèi)核Linux
zCore:使用Rust語言山寨微內(nèi)核Zicron
注意:這里說的山寨不是完全參考,不同語言也全參考不了,實現(xiàn)方式有很多不同之處。
上圖是王潤基同學(xué)惡搞了下谷歌Fuchsia的發(fā)布,改成自己的了真是新iPhone還沒出來山寨就有了。
總結(jié)下,這些OS其實都有一個技術(shù)指向:Rust+微內(nèi)核。
谷歌的Fuchsia比較難產(chǎn),所以逼急了又推出來一個KataOS,見之前文章:KataOS入門-簡介和代碼編譯,直接用現(xiàn)成的seL4微內(nèi)核+Rust應(yīng)用框架Sparrow搞了。
回歸正題,
1. zCore簡介
zCore 是用 Rust 語言重新實現(xiàn)的 Zircon 微內(nèi)核。
它運行在內(nèi)核態(tài),對外提供與 Zircon 完全相同的系統(tǒng)調(diào)用,因此能夠運行原生的 Fuchsia 用戶程序。
之前的文章介紹過Fuchsia的強大,其應(yīng)用程序更是兼容了安卓,另外對于微內(nèi)核驅(qū)動也是應(yīng)用,也可以應(yīng)用Fuchsia強大的驅(qū)動程序??梢娺@個zCore的巨大應(yīng)用價值。
2. 面向?qū)ο蟮膬?nèi)核
Zicron是用c++寫的,更適合用Rust重寫。有一個問題:什么時候需要面向?qū)ο螅?br />
假如世界上只有一個上帝,那就不需要面向?qū)ο?。但是世界上還有幾億的人,人都有非常多的共性,那答案就是有很多個實例的時候就需要面向?qū)ο蟆?br />
回到內(nèi)核,第一直覺是進程,這東西是多個的,特別是用戶進程,這必須可以面向?qū)ο蟀?,然后IPC通信,有很多進程直接又很多個通道通信,很多個就又可以面向?qū)ο蟆?br />
凡是可以有多個的東西,都可以面向?qū)ο?/strong>。
在c語言編寫的內(nèi)核或者宏內(nèi)核中,經(jīng)常用到抽象出來的結(jié)構(gòu)體,多個的表達就是結(jié)構(gòu)體數(shù)組或者結(jié)構(gòu)體鏈表,其輔助處理函數(shù)都要自己寫,例如查找插入改變值等,很繁瑣。
然后所有的東西都往進程結(jié)構(gòu)體PCB里面塞,很多機制理解起來很費力,要去看那個很大的PCB結(jié)構(gòu)體去理解,一下就懵了。
人還是容易理解抽象出來的事物然后加上簡單的思維邏輯,不抽象的混亂思維一會就暈了。
Zircon 是一個基于對象的內(nèi)核。
下面帶你領(lǐng)略下面向?qū)ο蟮镊攘Γ媸?strong>輕松學(xué)內(nèi)核的法寶。先來看一個zCore內(nèi)核運行時組件層次框架圖:
????
大家知道一般程序處理的流程:用戶程序-》系統(tǒng)調(diào)用-》內(nèi)核-》硬件里面去處理。
上圖中紅框里面就是把內(nèi)核里面跟硬件無關(guān)的元素抽象出來,用面向?qū)ο?/strong>的方法表示出來。
例如系統(tǒng)里面有多個Process,一個Process實例里面有很多個Handle和Rights指向其他的對象。
內(nèi)核對象相關(guān)的三個重要概念:對象(Object),句柄(Handle),權(quán)限(Rights)。
對象(Object):具備屬性和行為的客體??腕w之間可有各種聯(lián)系。從簡單的整數(shù)到復(fù)雜的操作系統(tǒng)進程等都可看做對象,它不僅僅表示具體的事物,還能表示抽象的規(guī)則、計劃或事件。
句柄(Handle):標(biāo)識對象的符號,也可看成是一種指向?qū)ο蟮淖兞浚ㄒ部煞Q為標(biāo)識符、引用、ID等)。
權(quán)限(Rights):是指對象的訪問者被允許在對象上執(zhí)行的操作,即對象的訪問權(quán)限。當(dāng)對象訪問者打開對象的句柄,該句柄具有對其對象的訪問權(quán)限的某種組合。
說下我的理解,內(nèi)核的資源都被抽象成對象,對象之間用句柄產(chǎn)生聯(lián)系,這種聯(lián)系為了安全性有權(quán)限限制,當(dāng)沒有句柄指向的對象也就是沒用了會被收回。
用戶程序操作內(nèi)核對象的一些細節(jié):
創(chuàng)建:每一種內(nèi)核對象都存在一個系統(tǒng)調(diào)用來創(chuàng)建它,例如zx_channel_create。創(chuàng)建對象時一般需要傳入一個參數(shù)選項 options,若創(chuàng)建成功則內(nèi)核會將一個新句柄寫入用戶指定的內(nèi)存中。
使用:獲得對象句柄后可以通過若干系統(tǒng)調(diào)用對它進行操作,例如zx_channel_write。這類系統(tǒng)調(diào)用一般需要傳入句柄 handle 作為第一個參數(shù),內(nèi)核首先對其進行檢查,如果句柄非法或者對象類型與系統(tǒng)調(diào)用不匹配就會報錯。接下來內(nèi)核會檢查句柄的權(quán)限是否滿足操作的要求,例如 write 操作一般要求句柄具有 WRITE 權(quán)限,如果權(quán)限不滿足就會繼續(xù)報錯。
關(guān)閉:當(dāng)用戶程序不再使用對象時,會調(diào)用zx_handle_close關(guān)閉句柄。當(dāng)用戶進程退出時,仍處于打開狀態(tài)的句柄也都會自動關(guān)閉。
總之,面向?qū)ο蟮拇a很清晰,很容易理解,不繞彎子,利用面向?qū)ο蟮恼Z法,代碼行數(shù)能大大縮減,預(yù)計5倍以上。上面的介紹大部分都是zCore教程里面的,這個教程更加的干貨,直接介紹核心概念,對OS基礎(chǔ)知識進行了省略。同rCore教程一樣也是從零開始自己寫一個OS的教程,這個感覺做的更好。
3. rCore整體架構(gòu)
zCore的設(shè)計主要有兩個出發(fā)點:
內(nèi)核對象的封裝:將內(nèi)核對象代碼封裝為一個庫,保證可重用
硬件接口的設(shè)計:使硬件與內(nèi)核對象的設(shè)計相對獨立,只向上提供統(tǒng)一、抽象的API接口
項目設(shè)計從上到下,上層更遠離硬件,下層更接近硬件,架構(gòu)如下圖所示:
為了讓 zCore 能夠同時運行在內(nèi)核態(tài)和用戶態(tài),我們在最下面設(shè)計了一個硬件抽象層(HAL),將內(nèi)核所依賴的底層操作封裝起來,在裸機環(huán)境和 Linux/macOS 環(huán)境上分別提供不同的實現(xiàn)。 在 HAL 之上的核心是zircon-object,也就是 Zircon 內(nèi)核對象,這里面包含了所有內(nèi)核機制的實現(xiàn)。
在對象層之上是系統(tǒng)調(diào)用層,它負責(zé)將內(nèi)核對象的功能封裝成 Zircon syscall ABI 暴露給用戶進程。 再往上就是整個 OS 的頂層模塊,它負責(zé)完成系統(tǒng)初始化和加載第一個用戶進程的工作,并將所有模塊組裝到一起,生成一個可執(zhí)行文件。 zCore 設(shè)計的頂層是上層操作系統(tǒng),比如 zCore、rCore、ZirconLibOS 和 Linux LibOS。
在項目架構(gòu)中,各版本的操作系統(tǒng)有部分公用代碼。與 zCore 微內(nèi)核設(shè)計實現(xiàn)相關(guān)的部分則主要是圖中左側(cè)藍色線部分。
乍一看,真是四不像,有點像嫁接,共用一個根,嫁接上不同的枝條,枝條上可以結(jié)出不同的水果。感覺這就是程序的高級玩法,殊途同歸,萬法歸一,還能相互轉(zhuǎn)化,實在是高,萬能工具啊。好處是,這幾種OS上的應(yīng)用都可以在zCore上運行,跟吃了幾種水果一樣甜啊。
4. OS界的變形金剛
不僅如此,它還可以作為一個普通的用戶進程運行在 Linux 或 macOS 的用戶態(tài),我們一般把這種模式稱為 LibOS 或 User-Mode OS。你甚至無需安裝 QEMU 模擬器,只需裝上 Rust 官方工具鏈,就可以編譯運行體驗 zCore!
git clone https://github.com/rcore-os/zCore --recursive cd zCore git lfs pull cargo run --release -p zircon-loader prebuilt/zircon既然可以用戶態(tài)運行,那么它其實就是一個普通的用戶程序。這帶來了巨大的好處:我們可以在用戶態(tài)開發(fā),用 gdb 配合 IDE 調(diào)試,用cargo test 跑單元測試,統(tǒng)計測試覆蓋率……這在之前的內(nèi)核開發(fā)中是難以想象的。
???
zCore 作為 rCore 的繼承者,它并沒有把前輩丟掉。事實上,zCore 并不是一個獨立的 OS,在它的倉庫里還藏著一個小 rCore!只需使用以下命令,即可快速把它召喚出來,我們來運行一個原生 Linux 程序——Busybox:
make rootfs cargo run--release-plinux-loader/bin/busybox????
這里面的奧秘在于,Zircon 作為微內(nèi)核,其實已經(jīng)提供了內(nèi)核中最關(guān)鍵的內(nèi)存管理和進程管理的功能。
我們只需在它基礎(chǔ)上補充 Linux 作為宏內(nèi)核的其它功能(例如文件系統(tǒng)),并對外提供 Linux 系統(tǒng)調(diào)用接口,即可重新構(gòu)造出一個新的 rCore。
這就是微內(nèi)核運行宏內(nèi)核程序的關(guān)鍵,缺的東西再加一層殼子,再封裝一層系統(tǒng)調(diào)用。
5.編程語言分析
官方 Zircon 是用 C++ 語言編寫的,代碼量約有 10w 行。而 zCore 只用了1w 行 Rust 就實現(xiàn)了其中大部分核心功能。雖然我們還差一些沒有實現(xiàn),但相差一個數(shù)量級的規(guī)模還是讓我感到有些詫異。
不過至少據(jù)我觀察,C++ 的 Zircon 代碼從設(shè)計上就比較復(fù)雜,用了各種自己造的輪子,并且充斥著魔法操作。相比之下,Rust 的 zCore 代碼看起來更加自然,核心庫自帶的基礎(chǔ)設(shè)施再加上一些社區(qū)庫的輔助,用起來還是非常舒服的。
關(guān)于 Rust 大家更關(guān)心的另一個話題是 unsafe。在 zCore 中我們盡量避免了 unsafe 的使用,但沒有絕對禁止(畢竟禁止就寫不出來了)。
據(jù)統(tǒng)計,在 HAL 之上大約有 20 個 unsafe,其中大部分用在了兩個對象之間互相取 Weak 引用的操作,剩下的也比較容易檢驗正確性。
而 HAL 之下 unsafe 就比較多了,由于貼近底層硬件,幾乎處處 unsafe,也就跟 C 沒什么區(qū)別了。不過好在 HAL 代碼還是比較少的,不過幾百行而已。
Rust 唯一的問題就是門檻太高了。然而對于編寫內(nèi)核這種對性能、穩(wěn)定性、安全性都要求極高的程序而言,門檻高一點未必是壞處。
在被 Rust 編譯器反復(fù)教做人之后,才知道自己當(dāng)初太天真,寫出來的程序處處是隱患。
async 機制除了上面提到的用戶態(tài)運行之外,zCore 還有一大創(chuàng)新之處:首次在內(nèi)核中引入了 async 無棧協(xié)程機制。
熟悉主流編程語言的朋友會知道,async 是近幾年開始流行的一種語言特性,能夠讓開發(fā)者用同步的風(fēng)格編寫異步代碼。它本質(zhì)上是將代碼變換成狀態(tài)機,在 OS 線程的基礎(chǔ)上又提供了一層輕量級的“協(xié)程”,使得程序能夠高效處理異步 IO,同時保持開發(fā)的高效率。
Rust 語言于 2019 年底正式穩(wěn)定了 async-await 語法,并于今年 3 月份的PR#69033中為 no_std 環(huán)境下使用 async 掃清了障礙。
這使得在內(nèi)核中全面應(yīng)用 async 機制成為了可能,而 zCore 可能是第一個吃螃蟹的人。(C++20 中也引入了同樣的特性,不過考慮到歷史包袱和生態(tài)問題,我比較懷疑能否真正用起來)
在傳統(tǒng) OS 中,每個內(nèi)核線程需要有自己獨立的內(nèi)核棧。當(dāng)線程掛起時,它的狀態(tài)就保存在棧上。
由于內(nèi)核線程可能很多,因此每個線程的棧都不能太大,在 Linux 中一般是兩個頁也就是 8KB。而在 zCore 中,所有內(nèi)核線程都變成了協(xié)程,在一個 CPU 核上共享同一個內(nèi)核棧。
當(dāng)進入用戶態(tài)時,內(nèi)核棧不再清空,因為要保留必要的信息,于是內(nèi)核-用戶切換的風(fēng)格從傳統(tǒng)的「用戶態(tài)中斷調(diào)用內(nèi)核處理函數(shù)」變成了「內(nèi)核主動調(diào)用函數(shù)切換到用戶態(tài)執(zhí)行」。
當(dāng)任務(wù)掛起時,協(xié)程的狀態(tài)被包裝成 Future 存儲在堆上。根據(jù)計算,目前每個 Future 狀態(tài)機的大小約為 600B 左右,大幅節(jié)省了內(nèi)存空間。
無棧協(xié)程相比線程的好處除了空間占用少以外,還有更小的上下文切換開銷,進而實現(xiàn)更高的并發(fā)和吞吐率。
不過它的缺點在于協(xié)作式、不可搶占,這可能會為系統(tǒng)的實時性帶來挑戰(zhàn)。關(guān)于二者之間的對比,還有待進一步的測試和分析。
zCore 的主要特性和創(chuàng)新點:
第一個完全山寨的 Zircon 內(nèi)核
使用 Rust 編寫,實現(xiàn)精簡,層級清晰
支持用戶態(tài)開發(fā)、測試和運行
第一個在內(nèi)核中使用 async 機制
總的來說,zCore 應(yīng)該是目前為止我們能想到、做到的,Rust 語言操作系統(tǒng)的集大成之作了。
6. 代碼下載體驗
已經(jīng)運行過rCore環(huán)境的機器,可以直接下載zCore的代碼體驗下。
下載命令:
Git clone https://github.com/rcore-os/zCore.git編譯運行命令:
cargo qemu --arch riscv64還是基于RISC-V硬件的qemu虛擬機運行:
審核編輯:劉清
-
模擬器
+關(guān)注
關(guān)注
2文章
862瀏覽量
43127 -
GDB調(diào)試
+關(guān)注
關(guān)注
0文章
24瀏覽量
1432 -
HAL庫
+關(guān)注
關(guān)注
1文章
114瀏覽量
6144 -
Rust
+關(guān)注
關(guān)注
1文章
228瀏覽量
6542
原文標(biāo)題:zCore入門-面向?qū)ο蟮腞ust微內(nèi)核
文章出處:【微信號:OS與AUTOSAR研究,微信公眾號:OS與AUTOSAR研究】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論