2017年2月25日 星期六

[嘴炮] 寫 os kernel 這件事


你必須要非常的努力, 才會看起來毫不費力
Tifa 很漂亮吧, 這次沒有專業技術, 純嘴炮, 什麼是嘴炮呢? 就是聽起來很厲害, 實際上完全沒幫助的東西, 偏偏大家又很愛看, 這技能很重要, 我要來練習一下。

看到強者我朋友這篇《別被 kernel 嚇到了》才有了這篇文章, 我和這位朋友的技術實力大概差了十倍, 之前差很大, 現在縮小一點, 大概是 9.99 的差距吧, 真的只有一點。

但其實我不這麼認為, 知識是有難易等級之分, 用 printf 印出 hello world 很容易, 改用 system call 難一點, 完全靠自己的程式碼寫出來呢? 難度一下子來到幾十倍的等級。

專業知識我自己把它分成幾個等級:
  • 很容易就找到的知識
  • 很容易就能理解的知識
  • 別人告訴你才懂的知識
  • 很難找到的知識
  • 別人告訴你, 你還是無法理解的知識
  • 別人告訴你你還是無法理解的知識, 又很容易忘記的知識
程式有難有易, os 被分類為難寫的程式, 相信沒太大爭議。演算法課本上或是某些公司的面試題目當然也不會很簡單, 但是能在 os 下寫程式已經是個小確性。

os 是屬於難度偏高的程式, 要學習寫 os 需要一些不太容易找到的知識, 像 compiler 一樣, 是屬於比較不流行的程式, 而這些程式總是有些神祕感。

而有一個最根本的困難點是: 寫 os kernel 沒有 library 可用。紅黑樹不會寫有 library 可用, xml parser 不會寫有 library 可以用, compiler 也都還有 lex/yacc 可用, 但有什麼 library link 一下後, 這隻程式就變成 os kernel 了嗎? 沒有! 寫 os kernel 程式意味著得自己打造所有的輪子。

而 os 程式的其他困難點是:

能使用的語言有限: 大部份都是組合語言和 c 語言。有「本事」的人還可以用他喜歡的語言來寫 OS, 例如 os by go, by Haskell, 《這篇文章》則是討論用來寫 os 的語言。而我相信大多數人並不是屬於有「本事」的這一族群, 所以我們還是用組合語言和 c 語言就好, 這已經足以難倒我們了。

JNode 則是用 java 寫的 os, 覺得很神奇嗎? 作者用組合語言開發 jvm, 再來就可以用 java 寫 os 了。算作弊嗎? 當然不算, 用 c 也是要用組合語言的。

要怎麼開始呢? 我能寫個 int main(void) 作為開始嗎? 要怎麼讓 pc/或其他硬體平台一開機就執行我的程式, 光這一小步 (bare metal) 就足以讓人辛苦一陣子。而寫 os 無可避免一定要用到組合語言, 所以還有個組合語言的門檻。要載入 os kernel 到記憶體中再 jump 去執行, 也是在 os 下少做的事情, 也需要對所謂的可執行檔有所熟悉。

除錯: os 下有各式各樣的 debugger 可用, 寫 os kernel 雖然也可以透過 bochs, qemu 等模擬器除錯, 但這些模擬器的結果並非是真的結果, 總是會有些出入, 這時候就得自己想辦法找出 bug, 那可不是普通的痛苦。以前沒有 bochs, qemu 等模擬器那辛苦程度就更不在話下。出動 ice 等級的工具也不是容易的事情, bios/uefi 開發公司, 就有這些 ice 工具。

了解執行檔格式/純粹的機器碼檔案: 這也是需要下點功夫才能理解。像 elf 這麼有趣的執行檔格式, 把它載入並執行, 絕對是很好玩的一件事情。

toolchin 的用法: 其他平台我不知道, 至少使用 gnu toolchain 開發 os 的程式有不一樣的用法, 也是要花點時間學習。linker script 就足以花上不少時間。

cpu 架構的知識: 這不會有人認為很簡單吧? 當然有簡單的 cpu, 但一樣不是速成知識。

c runtime: 一開始是用組合語言撰寫, 但在某個時機會想用 c, 要怎麼樣才能開始用 c 呢?每個平台可能不太一樣。這可是書上或網路上難找的資料。當然如果你想用組合語言完成 os kernel, 那就沒這問題, BareMetal-OS 就是用組合語言寫的。在這個知識上, 我跌了好幾次跤, 總算讓我獲得此技能, 這過程可不是普通的痛苦。

中斷程式: 這也是在 os 下很少練習的程式, 怎麼處理好中斷程式, 事實上它也是一大難題, 寫個一次, 你才真能理解 linux 上提到的 Interrupt Context, 而不是只有名詞上的理解。

context switch, 這個名詞資訊人個個琅琅上口, 不過要寫出這個功能可就不是每個人都做得到, 有了個這功能, 才有 os 的味道, os 有一個很重要的能力就是控制 process, 我要你怎麼跑你就怎麼跑, 不讓這個 process 執行就是不讓你執行, 這需要硬體相關知識才能完成, 很有趣的。

其他難題我沒提到: 因為我覺得不一定要有這些。檔案系統、記憶體管理、硬體資源的管理 ... 但有了才感覺比較像 os kernel 吧, 所以還有得忙。spin lock, mutex, semaphore, 這些東西要理解/使用都不容易了, 寫 os kerne 可是要實作出這些功能。

硬體的話還有: 你想存取硬碟吧, 只用 ramdisk 總是有點虛虛的, 你也想支援 mmu 分頁功能吧, 而這兩個加起來才能支援虛擬記憶體這麼潮的功能。網路時代你也許還想搞定那張網路卡。

這裡提到的東西都不是在書店中或是網路上很容易就能得到的知識, 就算找到了也要花費很大的心力去消化, 不是能輕易搞懂的東西, 而且很容易就會忘記這些知識。有些難度沒那麼高, 但是在 os 環境下很少練習到。

透過練習就可熟悉一件事情, 雖然我不是 100% 贊同這句話, 我認為有些事不是靠努力練習就一定成的, 還需要有天才般的頭腦。不過很幸運的是, 寫 os 程式不在那範圍裡, 它是可以靠努力練習而完成的。

但我同意強者我朋友中的一個論點, 不用把會寫 os kernel 的人看得比較「厲害」, 只要你願意花時間往這個領域發展, 一定能有某種程度上的成就。破解軟體也是, 若你往這方面發展, 也一定能有些小成就。你不會, 那只是因為你的學習領域在別的地方, 在你所會的領域, 會寫 os kernel, 或是破解系統的人不見得比你厲害。現在很流行的 web programming/手機 app 我幾乎一竅不通; 如何處理大型網站的流量, 我也沒有概念 (看過淘宝技术这十年後, 我已達略懂的境界); 對於破解/保護的議題我也不熟, 大家都是學有專精的程式員, 無需自抬身價也無需自卑。

而和一般的應用程式相比, 成就感可能也不高, 一般人不會欣賞 os 程式, process switch 交戶印出兩個字串, 懂的人會覺得「哇! 好厲害!!」一般人可能覺得就是印出兩個字串, 無三小路用, 成就感不高, 拿這時間去寫個 ios app 說不定得到的成就感還比較大。

為什麼要自己開發個 os kernel 呢?
Why develop an OS?》有個不錯的答案。

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。