CSP 課堂筆記之 Unikernel
Background
CSP 是上海交通大學軟體學院的研究生課程,因為之前大四上的時候沒好好上,特意重修了一遍,這裡是重修時候課上的一些記錄。
Monolithic Kernel
相信只要是接觸過計算機的,一定對『內核』這兩個字不會陌生。只要在使用電腦的時候,都離不開跟內核打交道。無論是Windows還是Linux等等,這些尋常使用的操作系統,都是用內核和管理和使用硬體的。
在這其中,最有名的是Linux Kernel,最早是由Linus實現的。看到這個標題還會點開的,應該都是聽說過Linux Kernel的吧。它是一個典型的Monolithic Kernel,也就是我們說的宏內核。
Monolithic,詞典義是『單一的,龐大的』,簡單理解,就是內核的所有功能,從文件系統,到內存管理,到CPU調度,等等等等,都放在內核態中。這樣做有一個很大的好處,那就是所有這些功能都在同一個地址空間下,大家做通信會非常方便,而且通信的成本肯定也是低的,實現起來會快糙猛一些。就是很莽很厲害。
但是,這樣也會導致一些其他問題。我覺得最大的問題就是代碼複雜度會提高。Linux Kernel的代碼量太美不看。同時,這樣也會導致容錯性不是很好,只要一個地方出了問題,會導致整個Kernel都掛掉。
Micro Kernel
那既然Monolithic Kernel有這樣的問題,做研究的人一定不會放過這樣的好機會,於是就有了微內核的概念。所謂微內核,是指內核只提供最必要的功能,比如IPC,內存管理,CPU調度等等。而其他,諸如文件系統,網路IO等等,都放在用戶態來實現。
這樣做的好處首先是內核變小了,內核是常駐內存的,小了自然就節約了內存的空間。但是,這樣的性能就會不如很莽很厲害的Monolithic Kernel要好,因為IPC通信的overhead還是有一些的。
Hybrid Kernel
那既然Micro Kernel和Monolithic Kernel都有問題,能不能把兩個結合一下,互相中和呢。
PPAP (Kernel Version)
I have a Monolithic Kernel.I have a Micro Kernel.Bow!Hybrid Kernel!
這大概是研究的慣用套路,一個事情有兩種極端的做法,然後中和一下,就有了第三種做法,公有雲,私有雲,混合雲也是這樣的套路,呃扯遠了。那Hybrid Kernel就是把一部分不常使用的內核模塊,或者是原本需要的時間就很長,因此IPC的overhead看起來就不是那麼誇張的功能,移出內核,而其他的就會放在內核里。
Windows就是這樣的內核,當然,這個是聽別人說的,不是很懂他們是怎麼看得到Windows的內核的,應該是論文吧,嗯。
ExoKernel
看上去,內核已經被研究人員們研究地沒得玩了。但ExoKernel又是另外一種內核,跟前面的幾種都有不同。而且ExoKernel的風格,感覺上跟Xen,kvm這樣的VMM有很大程度的相似,包括某些部分的實現,比如內存管理上。
之前說到的Monolithic Kernel也好,Micro Kernel也好,它們對資源的保護和管理都是在內核里去做的,也就是說,它們都是先對硬體做抽象,然後向上不直接暴露硬體,而是暴露硬體的抽象。一個例子,硬碟是硬體設備,但是我們的應用程序看到的是一個個的文件,文件本身就是一種抽象。而應用程序,是沒辦法直接操作硬體的,只能跟操作系統提供的抽象打交道。
那這樣無疑是使得寫應用的程序員不需要關心硬體,但是對於一些應用而言,其實是不好的。有一部分應用,就是需要跟硬體直接打交道。課上夏老師舉的例子,是說資料庫,MySQL,特別希望自己能夠直接跟磁碟來交互,這樣可以精確地確定它的索引等等文件的存儲位置,來針對硬體來做優化。
那這樣的需求,之前的內核都是沒辦法滿足的。於是,ExoKernel就被提了出來。Exokernel的設計思路是儘可能減少抽象層次,允許應用程序直接訪問硬體,而ExoKernel只負責保護和分配系統資源。應用程序過來請求資源,Exokernel看看資源是否空閑,如果空閑,直接交給應用,至於應用怎麼訪問是它自己的事。
ExoKernel分離了對硬體的使用和保護,使得應用程序可以直接使用沒有經過Kernel抽象的硬體,就很好很強大。但是這樣又有了其他的問題,那如果一個應用想發個HTTP請求,總不能先自己實現一套網路棧吧。於是,LibOS的概念就出現了
至於實現,其實有很多地方跟Xen很像,比如說都會用Software-defined TLB來做內存控制,就是在Flush TLB後,觸發TLB Miss就會trap到ExoKernel,這個時候會先檢查合法性,然後再填適當的緩存項到TLB中。要是沒有Software-defined TLB就用頁表來做。LibOS只能讀,不能寫自己的頁表,所有對頁表的寫,都會trap到ExoKernel,然後ExoKernel會在這次trap中做檢查,跟Software-defined TLB差不多,只是在不同層次的實現,但實現方式都是trap的方式。等等,還有很多地方。
LibOS
所謂LibOS,全稱是Library Operation System。LibOS提供對於硬體的抽象,與用戶代碼編譯成一個二進位,在同一地址空間。而且LibOS可以修改定製,來適配上層用戶對硬體的具體需求,如控制物理內存的相鄰等等。
這樣,不僅簡化了內核的設計,也使得應用可以針對硬體做優化。但是,缺點是內核里沒有進程調度,所以沒有真正的多進程,而是靠Kernel來進行資源的分配。
UniKernel
Unikernel是一種LibOS,它有著自己的哲學,那就是一個操作系統應該只有一個進程,內核和應用都在一個地址空間內。這樣的好處就是,可以使得這個操作系統,或者說應用,非常地快。因為操作系統所有的資源都是這個應用的,而且所有對象都在一個地址空間里。還安全,相當於是可以剪裁原本的Monolithic Kernel,拋棄掉不用的功能,只把需要的硬體抽象Library編譯到二進位裡面。
有這麼多好處,不是它火的關鍵,最關鍵的是雲計算的流行。Unikernel可以直接運行在Xen上,而且不像傳統OS那樣,它小,而且安全,還快,簡直就是天生為雲計算而生的。從某種程度而言,是雲計算中理想的Guest OS。
不過它也有一個廣受詬病的缺點,就是沒辦法調試,不過我覺得這個倒不是關鍵,因為在開發的時候可以不用UniKernel,而在生產環境中再編譯出UniKernel再去部署。還有就是硬體支持比較困難,會導致Library的碎片化,這個問題還挺嚴重的,就像安卓一樣,不知道有沒有解。
UniKernel從某種程度而言,衝擊了容器的地位,但是其實容器也是可以跟UniKernel一起來用的:
尤其是現在有了runc,使得兩者的結合更加明朗了。
推薦閱讀: