操作系統內核寫後感

  最近用的幾個月的時間,大體寫了一個簡單的微內核的操作系統內核,還是想繼續寫下去,關於一個簡單的內核開發有一些思考。

  首先要選定好語言,我剛開始想用C來寫,但是一想現在很多書都是用C來教學寫內核的,如果我也用C,那我那容易就由於慣性,把人家的代碼抄上了,所以決定用C++來寫,但是用C++寫的時候,又發現了一些問題,比如無法使用運行時庫,對於C++運行時的特性無法使用,甚至全局對象都不構造(也需要運行時庫),也就成了C with class,而且寫的時候我的思路是,先用C的寫法實現一下,沒問題了,再用面向對象來寫,但是一發不可收拾,當我反應過來的時候,已經很難重寫了,所以後來的代碼有面向對象的思想,也有C語言的寫法,成了兩不像,而且此時也很難用C重寫,因爲一些命令空間,對象等問題,重寫起來太麻煩了,非常後悔。如果再給我一次機會,我寧願選擇用C來寫。

  還有就是內核的開發過程,我們學習操作系統的時候一般是按各模塊來學習的,比如先學內存,然後進程調度,也就是橫向的,但是我覺得,這個方式對於理解內核是非常有利,比較友好的,但是對於內核的開發和設計來說並不友好,因爲從一個設計者的角度來講,應該更關注整個系統,各個模塊間的關係。所以我覺得對於設計者,不應該從學習內核那種橫向的思維,直接劃分各個模塊,而應該是縱向思維,第一個維度,比如一些命令的實現,如何解析elf文件,如何進入保護模式,如果開啓分頁,這些東西一百個內核,也就那一種寫法,設計者不應該在這上面浪費時間; 往上一個維度,就是各模塊內的算法,比如內存的分配算法等,這些一百個內核或許有五十種不同的實現,但其評價標準比較單一,好或不好,最終肯定都採取那種最好的方式。最後一個維度就是各模塊間的關係,比如各模塊如何通信,系統應更關注安全,還是效率或者其他,這一層一百個內核也許有一百種寫法,這纔是內核的靈魂,纔是設計者要考慮的東西,而不是如何實現命令,如何進行內存分配。

  對於各模塊間的關係,不光包括運行時的關係,更包括開發過程中的關係,比如是否爲了提高效率,可以允許破壞在源碼層面上的封裝性。在寫這個內核時,遇到地址空間的問題,前面幾篇文章已經說過技術問題,現在從設計角度說一下其問題,由於爲微內核,所以內存管理和內核(含進程調度,有pcb)是分開的,但是如果要實現獨立的地址空間,比如進程地址空間(虛擬地址空間)用頁表來維護,那把這個頁表交給內存管理系統還是內核來維護呢? 按理說應該讓內核中的pcb來維護,畢竟是身份證嘛,進程相關資源都在這,但是如果交給它來維護,但是申請內存的時候怎麼辦?假設虛擬地址空間由位圖來維護,內核在切換進程的時候,頁表確實切換了,也就是地址空間切換了,但是維護虛擬地址空間的位圖怎麼辦?申請內存的根據呀,也得相應改變吧,這叫需要通知內存管理系統,但是通知通過又需要切換,陷入遞歸,不可取,或者說系統協商好位圖的位置(虛擬地址),像棧一樣,就在0xc0000000上,比如把位圖都映射在虛擬地址0x12345678上,申請或釋放內存時內存管理系統直接從這讀取位圖,但是這個位圖必然要由內核來初始化,內存管理系統只能使用,內存管理系統有些名不副實了(但這應該是這幾種方法裏比較好的一種了), 如果把這個位圖交給內核來維護,就相當於把這個內存管理系統的數據結構暴露給了內核,破壞了模塊間的封裝;  如果把頁表交給內存管理系統來維護呢?這是進程的資源,肯定要與進程一一對應,既然一一對應,也就意味着進程表長度爲NR時,內存管理系統也要維護一個長度爲NR的數組來維護進程們的虛擬地址空間(位圖同樣也要對應,破壞封裝),這也破壞了源碼上的封裝(內存管理系統需要知道進程表的長度),而且交給內存管理系統來維護又有許多問題,每次進程切換時要切換地址空間吧。但是地址空間存放於內存管理系統,怎麼辦呢?內核在切換的時候向內存管理系統請求唄,拿到地址空間再切換,但是切換時又遇到了上面同樣的問題,遞歸了,也不可取。

  所以我覺得,內核設計應該更關注整個系統,模塊間的關係,而不是某個模塊的算法,在設計,效率,安全等方面作出取捨。

比如對於一個看重設計的內核來說,哪怕一段代碼再漂亮,再高效,只要違反設計的初衷,就不會把它合併進來,所以這些纔是內核的靈魂。值得討論和思考的東西。

 

上面關於地址空間交給誰來維護的問題,有上面的思考過程,但沒有源碼實現過,如果有問題,歡迎指正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章