1. 如何從零開始寫一個簡單的操作系統
如何從零開始寫一個簡單的操作系統?
看了這個:從零開始寫一個簡單的操作系統 求指教。
知乎用戶 學生生涯只剩半年。
548 人贊同
終於可以來回答這道題了……
一年多前,也就是大一下學期末的時候,我看到這個問題下 @fleuria 叔的答案,然後看了 F 叔給的這個鏈接 基於 Bochs 的操作系統內核實現 ,當然是什麼都看不懂,除了驚詫之外也了解了一件事情:一個人寫一個簡單的操作系統內核是一件非常帥氣並且可行的事情。
於是我開始寫了,那時候我的水平大概是:只會做 C 語言的習題,編譯的話只知道按 F9,匯編知道常見的指令,另外會一點點的 Win 32 編程,能流暢使用 Windows。
一開始我找了《30 天自製操作系統》來看,每天看書,然後把從書里把代碼打出來,一次一次地編譯運行。因為要同時寫匯編和 C,所以從那時候起就開始用 vim。
在啃完了差不多半本書後,開始覺得沒意思了……因為覺得作者為了讓內容更簡單而省略了太多細節。也看了於淵的《Orange『s 一個操作系統的誕生》,依然沒看下去:匯編用得太多了。期間也曾斗膽發郵件給 F叔,然後他推薦了 Bran's Kernel Development Tutorial 這個教程,於是我就從這教程重新開始了: 「30天自製操作系統」 Stop & 「OS67 」 Start
那時候大概是大二上學期,於是在 github 上又開了一個 repo,一開始在 Windows 下開發,後來又切換到了 linux 下,因為 Bran's 用的 bootloader 是 Grub,不符合我的初衷,所以就自己寫了一個,之後便跟一路教程寫,跨過了保護模式這道坎,完成了基本的設備驅動。
在完成 Bran's 後,我又部分參考了 寫一個操作系統內核有多難?大概的內容、步驟是什麼? - To淺墨的回答 中推薦的:hurley25/hurlex-doc · GitHub 文檔,完成了一些簡單的調試函數和庫函數,printk 和內存分配。
事實證明,盡早寫好調試函數諸如 panic, assert 和 printk 是非常重要的。 大量地使用有助於你盡快地發現 bug (當然前提是這些函數本身不能有 bug)。
看完了 hurlex-doc 該看的部分後,很長一段時間了都不知道該幹嘛好,模仿 hurlex-doc 里的內核線程切換也一直出錯。這一情況一直持續到我開始讀 Xv6, a simple Unix-like teaching operating system 。
如果你去看知乎關於「自製內核」的問題,你會發現 xv6 被反復地提及並推薦,事實上它非常值得被推薦:這是我讀完大部分代碼之後真切體會到的。
之前的 Bran『s 和 hurlex-doc 的篇幅都比較小,我是在電腦和 kindle 上看完的,xv6 相對來說代碼量比較大,有 9000+ 行和一份文檔,之後我又找到了這個:ranxian/xv6-chinese · GitHub xv6 文檔的中文譯版,所以我就去花了十二塊錢學校列印店列印了一份中文文檔和一份代碼。這又是一個正確的決定,讓我不必對著電腦就能看代碼。
在之後的時間里,我先讀了 xv6 中文件系統相關的部分,然後改寫它的代碼為我的內核添加了一個 類似 Minix 的文件系統。 然後幾乎又照抄了其中了進程調度的部分(做了部分簡化),又在原來的代碼基礎上為添加操作系統的介面,接著寫用戶程序,過程幾乎是「一路順風」。看 xv6 的那段時間也經常是處於醍醐灌頂的狀態。
最後我終於在差不多一個月前完成了這個簡陋的操作系統內核:
LastAvenger/OS67 · GitHub (沒錯其實我是來騙 star 的)
歷時一年,一路點亮了不少技能樹(雖然都點得不好),這樣算是「從零開始寫一個簡單的操作系統」么? 跟進一步說,有誰不是從零開始的呢?所以想做的話,現在就開始做好了。
這是被「翻爛」了的 xv6 源代碼和中文文檔(其實是放書包里被磨爛了)
「故事」講完了,接下來說一點經驗之談吧……
* 知乎上總是有人在討論「做一個玩具編譯器和做一個玩具內核何者更有趣」之類的問題,然後總有各種大V 跳出來說內核有多 dirty 而編譯器多 clean,事實上除了 CPU 上的幾個表因為歷史原因長得惡心一點,內核並沒有什麼特別 dirty 的地方,另外,想做點什麼打發時間,不過是兩個代碼量稍多的入門項目,有什麼好糾結的?
* 寫內核的過程中,你會接觸到一些這輩子大概只會用到一次的知識,A20 線已經成為歷史,日常的編程裡面也不需要你懂得 GDT IDT 的結構。但是單憑內核主要部分部分(文件系統,進程,內存)給你帶來的知識而言,這點冗餘是值得的。
* 盡早實現調試函數並大量使用,善於利用 bochs 的內置調試器,能省下你不少時間。
* 有時候覺得書里的做法非常奇怪,你覺得你有更好的做法,一般是你想錯了。(當然只是一般)
* 上面說看 xv6 一路順風是假的,20% 時間在抄代碼,80% 的時間用來調試。
* 對我這種能力一般的人來說,「寫內核」只是好聽的說法,正確的說法是「抄內核」。當然,就算是抄一個,也算是受益匪淺了。
* 抄 xv6 的好處在於,即使你的代碼出錯了,你可以堅信,正確的答案肯定在 xv6 的代碼里,或許只是你還沒理解透而已,只要不斷地看和理解,你就離正確的道路越來越近。
最後,感謝 @fleuria 在微博和郵件里的多次幫助, @To淺墨 的 hurlex-doc 文檔,鮮染同學翻譯的 xv6 中文文檔, @郭家華 完美地解答了我一開始的疑問,讓我在內核中得以使用 C 語言。
在 #archlinuxcn 頻道里也得到了很多人的幫助。
發布於 2015-11-09
邱永臣 喜劇演員,兼開發工程師
890 人贊同
大二的時候,老師(中山大學萬海)對我們說:「如果有誰能自己寫一個內核出來,那麼,他平時可以不來聽課,也不用做平時作業,做出來還能加分,怎麼樣,有沒有人有興趣?」
和老師一番討價還價之後,我成為全年級幾百號人里唯一一個自己寫內核/整個學期都不去教室聽課/任何作業都不做的那個人(代表著我的身邊將沒有可以提供參考的人,任何資料都只能自己找)。
一開始買了《30天自製操作系統》,上面寫著需要軟盤還有其它的模擬器,我的初衷是寫一個可以燒在真機上一按開機鍵就能跑起來的那種,所以看了幾頁後就丟開了。後來又找了國人寫的一本,也不是特別符合,也丟開了。
這時我看到了那本教材(俗稱綠寶書),約莫800頁。之後的兩個星期里,我每天泡圖書館,以每小時10頁的速度讀完了它,在上面亂塗亂畫了許多標記。800頁的英文書,我從中學到了大量的基本概念(線程進程,內存演算法,定址方式等等)。
接著我尋思直接從網路上而不是從書上尋找資料,TA師兄給我提供了一個OS Development,我照著上邊的例子,寫了數以千記的匯編代碼,習得了匯編技能。
此時,我具備基本的概念知識,對程序的語言也已經理解,知道了虛擬機的調試方法,差的,就只有對內核整體是如何協作不太明白。於是我去找來老師用於教學的PintOS,找來MIT那個項目的代碼,還有國內一個高校自製的OS(是幾個研究生一起寫的),仔細研究了一遍,最後開始寫代碼。
在那個學期里,我放棄了LOL,一心看代碼,寫內核,寫各種模塊,將過程記錄在博客上,花了三個月的時間,最終寫出一個具備terminal的內核(文件系統沒寫好,時間不夠),可以跑命令,運行函數,管理內存和進程,處理中斷。
--------------------------
這個Tittle非常好,衷心希望不要因為莫須有的理由封殺。