教練,我想自幹作業系統! - ianchen0119/AwesomeCS GitHub Wiki

前言

寫一個 OS 是多麼美好的事,在有限的生命中千萬不要遺漏了它。 -- 王佑中博士

筆者在開始撰寫本系列文前不曾接觸過嵌入式系統開發,也很少觸碰 C 語言,不過,在看到 COSCUP 2012 的第一次自幹作業系統核心就上手的議程錄影後受到不小的衝擊。雖然我不像 Jserv 大大能在短短的 20 分鐘內自幹作業系統。但是,我們也可以透過閱讀相關文獻以及專案原始碼更加了解作業系統這個有趣的學科。

此外,James Bach 說過一段筆者非常喜歡的話,在這邊分享給大家:

假如

你能把重要的事做完

別人有看到你在自我學習

別人看到你在學習做事,即使你不確定該怎麼做

你無私地和人分享你所學的東西

你不隱藏你的無知,也不安於你的無知

你尊重別人所知洞悉

你通常知道如何找到你所不知道的東西

你知道如何尋求幫助

你提供對別人的幫助,而且是以他的方式幫他

那麼

沒人會在意你的成功是來自自學或是已知的知識

沒有會在乎你偶爾的失誤

沒人會在意你在某個時間不知道某種特定知識

如果你跟筆者一樣是個喜歡作業系統但是平常沒有在接觸 C/C++ 的人,我認為這並不是什麼太嚴重的問題,畢竟 C 語言就是設計來開發 UNIX 作業系統的,所以在學習作業系統的過程中一定會越發熟練 :D

開發實務

在實務上,我們用來開發的平台可能會與目標平台有出路,例如: 在 x86 平台開發 RISC-V 的作業系統,這時候我們就會需要利用 Cross Compiler 去做處理。

專有名詞

這邊紀錄了一些系統程式開發的專有名詞,如果讀者覺得過於陌生,也可以參考我事先錄製的影片

Host

  • Compiler
  • Debugger
  • Editor code
  • Kernel code (target)
  • Editor
  • Host computer

Target

  • Target computer
  • Assembler
  • Linker
  • Lib
  • Cross compiler

Complex program

  • Makefile

  • Linker script

  • Simulator, Emulator, VM

    • Simulator

    單純用軟體去模擬,就好比我們用物件導向寫了一個機器人程式,他就算是機器人的 Simulator。

    • Emulator

    Emulator 比其軟體模擬,它能夠直接/間接的操作硬體,以 QEMU 為例,它就是一個十分接近真實電腦的 Emulator。

    • VM

Debugger

  • Cross debugger

    Cross debugger 用於對 Target 上 application 的除錯,就好比 Debugger 與 Host computer 的關係。

  • Kernel debugger

    常見的 Debug 工具: kdb, kgdb, gdb,本系列文也在 gdb 的介紹時提過如何在嵌入式系統開發中使用 gdb。

  • Cross kernel debugger

  • ICE

方便開發的工具/重要概念

GNU Debugger

GNU Debugger,簡稱 GDB ,是 GNU 軟體系統中的除錯器,由於其具有可移植的優點,在現今的主流處理器架構與作業系統平台上都可以看見 GDB 的身影。

更多細節請參考 GNU Debugger 一文。

MakeFile

Make 是一套自動化建構軟體,它讀取名為 Makefile 的檔案,並根據使用者輸入的命令找到 target 後生成命令轉交給 shell 去執行,以生成開發者需要的可執行檔案。 不只如此, Make 還具有依賴關係的檢查系統,可以幫助開發者高效的進行測試與編譯工作。

更多細節請參考 Makefile 一文。

Patch

比較 A 與 B 版本的差異,將其整理出來做成 Patch。

Git

版本控制工具,方便我們處理多人開發時產生的衝突問題。

更多細節請參考 Git 與那些多人混戰的開發經驗談一文。

Memory Layout

Memory Layout

  • Stack: 存放函數的參數、區域變數等。
  • Heap: 一般由程式開發者分配,執行時才會知道配置大小,像是常用的動態分配技巧 malloc / newfree / delete

    注意: 其資料結構不是 heap 而是 linked list。

  • BSS: 未初始化的靜態變數
  • Data: 全域變數、靜態變數
  • Text / Code: 常量字串

Linking

實務上,我們會將寫好的 C Code 編譯成 *.o 檔,再透過 Linker 輸出成可執行檔案,像是 *.out*.elf 等。在本系列之前的文章中已經向大家介紹過組譯器以及連結器、可執行與可鏈接格式 elf,因此,本篇不再多做介紹。

安裝 GNU Toolchain

在正式進入系統程式的教學之前,我們需要安裝支援 RISC-V 的編譯工具包,才能編譯出可運行在 RISC-V Target Machine 的執行檔:

  • Linux 如果你是使用 Linux 系統做開發,可以直接參考 GNU Toolchain 的官方說明。
  • Windows 10 若你是使用 Windows 10 開發,可以透過上方連結安裝由 Si-Five 提供的開發工具,它已經內建了 GNU Toolchain for RISC-V。 安裝完成後,請記得將以下路徑添加至環境變數:
D:\install\FreedomStudio-2020-06-3-win64\SiFive\riscv64-unknown-elf-gcc-8.3.0-2020.04.1\bin

D:\install\FreedomStudio-2020-06-3-win64\SiFive\riscv-qemu-4.2.0-2020.04.0\bin

為了避免相容性問題,建議安裝 FreedomStudio-2020-06-3-win64 版本。 此外,當要運行之後介紹的範例程式時,也請使用 Git-Bash 進行操作:

未來一周

說了這麼多,來聊聊接下來一周會做些什麼事情吧! 我們將會在這一周學習作業系統的相關知識並且透過閱讀開源作業系統的方式了解這些理論是如何轉換到實務上的。可能會參考的開源專案有:

  • mini-riscv-os 由金門大學資工系的陳鍾誠老師開發,是一個大約 1000 行規模的作業系統,該專案主要重現了:

    • 內文交換
    • 排程演算法
    • Timer Interrupt
    • PLIC 支援
    • Spinlock
    • Block Device Driver
    • Memory Allocator

    我們可以透過這個簡易的作業系統了解電腦如何在開機時加載作業系統,是個很棒的教材,從筆者開始編寫該系列文到現在,已經嘗試並成功貢獻了一些原始碼到該專案上,我貢獻的部分主要包含了:

    • lib_getc (方便日後擴充 Shell )
    • Spinlock

    保護 Shared data。

    • PLIC 支援

    處理更多的外部中斷,包含: UART IRQ, VirtIO IRQ 等。

    • Trap Handler 的改良

    原本 mini-riscv-os 僅支援時間中斷的處理,我修改了其 Trap Handler 的實作,使其可以處理與辨認不同的中斷以及異常狀況。

    • 移植 xv6 的 Block Device Driver 實作

    要實作 File system 之前,必須讓作業系統可以操作虛擬硬碟上的資料,所以 Device Driver 就非常的重要了。 有了 Device Driver,除了存取硬碟,系統還可以與網路卡、顯示卡等外部設備做溝通,不過這就超出筆者目前的能力範圍了 XD

    • Memory Allocator

因為筆者是 mini-riscv-os 的貢獻者之一,所以專案中的中文說明文件會與本系列文的內容相似,請讀者們別誤會,我絕對沒有做出抄襲的行為。 並且,此系列文也有受到陳鍾誠老師的鼓勵,希望這些文章可以幫助到更多人 : )

  • xv6-riscv

    xv6 是由 MIT 開發的作業系統,其也被用作教學上,該專案最一開始是基於 x86 開發,隨後也因為 RISC-V 的流行而產出可運行在 RISC-V 平台上的版本,xv6 具有完整的檔案系統以及系統呼叫,其規模要比 mini-riscv-os 要大 10 倍左右。

    在 Github 上其實有很多 xv6 作業系統的變形,像是:

Reference