這是一本線上可取得的免費書籍,作者為趙炯博士,現為同济大学机械工程学院机械电子教研室副教授,可於作者網站 www.oldlinux.org 下載這本書

故事

這本書是2019二月同學介紹給我的,我甚至記得我們是晚上在學校福利社外面遇到。在回家後讀了序言和第一章我就知道一定要讀這本書。至於為什麼,是因為我一直對作業系統很有興趣,具體來說是想要知道一個OS到底是怎麼寫出來的,而好笑的是在學校修了作業系統之後這個問題完全沒有獲得解答。

如同書上序言所述,無論是大部分學校的OS課程,或者各種教作業系統的書,都只能直觀的描述OS的重點功能和概念,或者拿出幾行程式碼來討論。在沒有對整個code base有綜觀的理解的情況下學習起來容易有盲人摸象、浮沙築高臺的感覺,說難聽一點就是不知道實際上在幹嘛,而且抓不到整體的結構,更別說學到怎麼寫作業系統了。

所以我一頭栽進去,一千多頁的書不會幾週就讀完,我有空就幾頁幾頁的看。前三章是先備知識,不難,但讀了第四章,介紹x86架構我就知道要另外找其他資源加強,不然後面一定讀不下去,所以我暫時擱著這本,花了兩個月時間讀過⟪x86匯編語言 從實模式到保護模式⟫,把x86這個洞補起來。

接著是第六、七章,講解開機和初始化的部分。這兩章有承先啟後的效果,因為開始有講解程式碼的註釋,必須了解前幾章的內容才能理解這裡的程式所運行的效果、環境以及用途。我還記得第六章開機的內容全部都是x86組合語言,讀起來真的有點痛苦又很慢,在讀完之後,知道後面大都是C code的情況下真的有解脫的感覺,不過看著程式一行一行的建構出電腦的初始運作環境,感受還是踏實的。第七章是個很神奇的章節,OS進行最後的準備工作,準備讓使用者使用。看到中間突然有個頓悟的感覺,整個Linux0.12內核的運作在腦海中形成,理解上的迷霧消散,有種「哦我突然懂了!」的感嘆,太讚。

後面幾章大都在講解目錄樹中各個資料夾,一章講解一個資料夾。最後一章是用模擬和用真實機器編譯和執行這個舊版linux的方法。整本書掃完大概花了我一年,中間充滿許多的懷疑,也有一些焦慮。除了某些地方完全讀不懂之外,有時候進度奇慢無比,可能讀個兩三頁就要花我一個小時以上,偶爾會想我到底哪時候可以看完這本書。滿開心我有堅持到最後,翻到最後一頁的一天也到來了。

當然,我沒有因為看完了這本書就知道怎麼寫一個OS,但至少從頭到尾體驗過了要實作一個內核需要哪些東西,對OS的認識也清晰了許多,現在的我和去年這時候的我對作業系統的認識可以說是不同級別的,能遇到這本書真的很幸運,對於往後的成長也有了更明確的方向啦。

介紹 (與書中的內容說明相同)

本書對 Linux 操作系統早期內核(v0.12)全部源程式文件進行了詳細全面的注釋和說明,旨在讓讀者能夠在盡量短的時間內對Linux的工作機理獲得全面而深刻的理解,為進一步學習和研究現代Linux系統打下堅實的基礎。雖然分析的版本很低,但該內核已能夠正常編譯運行,並且其中已包括了 Linux 工作原理 的精髓。書中首先概要地介紹了 Linux 內核發展歷史,說明了各內核版本之間的主要區別和改進方面,給出了選擇 0.12 版內核源代碼作為研究對象的原因。然後給出了閱讀內核源代碼所需的相關基礎知識,概要介紹了運行 Linux 系統的 PC 硬體組成結構、編制內核使用的組合語言和 C 語言擴展部分,並且重點說明了 80x86 處理器在保護模式下運行的編程方法。接著介紹了內核程式碼概況,給出了內核源代碼目錄樹結構,並依據該組織結構對所有內核程式和文件進行了詳細描述和說明。為了加深讀者對內核工作原理的理解,書中最後一章給出了多個相關運行debug試驗。書中所有相關資料和資訊均可從網站 www.oldlinux.org 下載。

先備知識

如果要讀懂這本書,以一般資工系修課來說最好先修過系統程式、作業系統、計算機結構這三門課,而除了這些,Linux、執行檔格式、工具鏈、編譯鏈接流程等也最好有一定的了解,最後一項最重要的就是一定要熟悉x86架構,書上雖然花了第四章一整章來介紹,但我認為還是太少,短短68頁是沒有辦法好好交代完x86的。我自己在讀的時候感覺很不扎實,所以花了兩個月時間讀了⟪x86匯編語言 從實模式到保護模式⟫,再加上找了很多其他資料,才把x86摸得比較透徹。

相對的weak parts

這本書有一千多頁,算是很厚的一本書了,但是對於一個完整又詳細的計算機系統來說這樣的篇幅終究還是太少了,有些方面的介紹只是隨筆帶過或寫得比較艱澀,除了上面提到的x86架構之外,這裡再列出幾點:

講解較少:

  • a.out格式
  • 執行檔載入、鏈接過程與原理
  • signal (restart syscall部分)

我認為比較艱澀(有些我還很不懂):

  • MINIX檔案系統
  • 檔案系統掛載(mounting)
  • 鍵盤驅動
  • tty概念
  • 底層I/O
  • memory management

其他書籍

以下是我讀過,覺得對於理解這本書有幫助的其他書籍:

  • ⟪The C Programming Language⟫
  • ⟪x86匯編語言 從實模式到保護模式⟫
  • ⟪程序員的自我修養⟫

閱讀建議

以下是我在讀這本書時歸納出的一些閱讀方法,供大家參考:

  • 邊讀邊參考Bootlin Elixir Cross Referencer,好用
  • 心態
    每個人程度不同,我認為可以先評估一下自己的程度調整閱讀的心態,決定要讀到什麼程度,該省略或者跳過那些部分,基本上不要假設自己很仔細讀就可以把整本書完全理解,除非程度真的很高而且非常熟悉以前個人電腦的各種運作細節。
    以我的作法舉例,省略的部分我跳過了磁片、數學協處理器的章節,因為磁片現在漸漸淘汰,數學協處理器的部分對內核的了解也沒有很重要,至於讀code的時候如果沒辦法完全懂我也會先求把文字講解部分讀懂,而如果連文字都很難理解那我就果斷跳過,畢竟有些內容實在是很老舊,不然就是要額外花大量時間才能學懂,前提是不大幅影響自己對內核運作的理解。
  • 先看一個檔案前後的說明
    書中會一個檔案一個檔案的說明講解,對每一個檔案會先有總體說明,然後進入程式碼(中間穿插非常多作者的註釋),然後檔案結束後會有補充說明。這邊建議先讀完前面的總體說明和最後的補充說明再讀程式本身,因為有些說明只有在後面的補充說明才有,我原本只照順序讀,然後讀到程式時摸不著頭緒,直到看到補充說明才知道程式在幹嘛。
  • 看一點說明就看一點code
    程式的註釋很多時候長這樣:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int func()
    {
    // 作者說明1
    // 作者說明2
    // 作者說明3
    some code a;
    some code b;
    some code c;
    some code d;
    }
    會有一塊一塊的文字和一塊塊的code,在文字和code都很大塊的時候建議不要看完整個說明文字再讀code,建議看一句文字就看幾行程式,會比較好理解。
    e.g. 說明1 -> some code a -> 說明2 -> some code b, c -> 說明3 -> some code d.
  • 有些函式local variable跟argument都很多要注意
    我發現在讀code時,因為local variable和function argument有時候很多會造成混亂,建議多加注意哪些值是傳進來的哪些是local。
  • 章節閱讀順序
    我是照著順序讀的,不過後來發現這不是最好的做法,我覺得比較好的章節順序是把header file和記憶體管理放到前面:
    (前面序號為閱讀順序)
    1~7. 不變
    1. 第十四章 header files
    2. 第三章 記憶體管理
    3. 第八章 kernel
    4. 第十二章 file system
    5. 第九章 block driver
    6. 第十章 char driver
    7. 第十五、十六、十七章
      block driver 和 char driver 也可以放到記憶體管理前面,就看喜歡top-down還是bottom-up的方式。