Linux核心工程師是怎麼步入核心殿堂的?
在知乎上看到了這個ofollow,noindex">問題 ,藉機總結一下自己在 Linux 核心學習研究上的經歷和方法。
目前的工作實際上不是在搞 Linux 核心,但讀大學的 4 年,其中有兩年的時間在研究 Linux 核心和嵌入式 Linux。雖然已經好多年沒再搞 Linux 核心,但上次專案需要,還是分析除錯了 Android 的 low memory killer 驅動,並給 Android 的 binder 驅動增加了一些功能,對於 Linux 的核心的基本分析除錯能力一直在。看到這個問題,分享一下自己的做法。
以我的理解,題主的問題可以分解為三個小問題,Linux 核心開發需要知道的基本背景知識,Linux 核心開發研究在技術上的路線圖,以及 Linux 核心開發過程中的分析除錯手法。
Linux 核心開發需要的基本背景知識。為什麼說是“基本”呢?主要是因為,如我們從作業系統原理一棵中所知道的那樣,作業系統核心都是分為基本大的子系統的,如 I/O,任務排程,記憶體管理,檔案系統和網路等等,這些子系統都是演算法密集型的系統,不同子系統需要的背景知識還不太一樣。
Linux 核心主要是用 C 語言寫的,因而 C 語言開發的基本功必不可少。C 語言開發學習的經典著作很多,不僅有C程式設計語言 這樣長生不衰的權威之作,還有,還有“C 語言開發的四書五經”和 C 語言開發——現代方法 這些非常好的作品。作業系統核心作為一個數據結構和演算法密集型的領域,基本的資料結構和演算法知識不可或缺,資料結構 這本必修課自不必說,其它還有演算法導論等等經典。
想要研究 Linux 核心,站在使用者的角度來看待它,瞭解它的功能和介面是必須的。誰是 Linux 核心的使用者,Linux 核心又為使用者提供了什麼功能,使用者又是通過什麼介面訪問這些功能的呢?Linux 核心功能主要是通過系統呼叫暴露給使用者的,系統呼叫通常又被封裝為 C 庫,需要使用作業系統核心功能的開發者通過 C 庫使用 Linux 核心。相關領域非常經典的著作是UNIX環境高階程式設計(第3版) ,讀了這本書,應該就大體可以瞭解到,作業系統提供的大概就是檔案操作,程序執行緒操作等功能了。程式設計師的自我修養 也值得一看,可以瞭解一下程式載入執行的過程。
然後是作業系統原理和計算機體系結構。使用者空間看到的作業系統功能和作業系統內部通常的設計結構並非嚴格對應的。通過作業系統原理,可以讓我們看到作業系統內部通常的設計結構,如通常的子系統劃分, I/O,任務排程,記憶體管理,檔案系統和網路等,多個子系統的功能,都按照“一切皆檔案”的 Unix 系統經典理念,通過檔案有關的介面暴露給使用者空間。作業系統原理有關的經典著作有斯托林斯的作業系統——精髓與設計原理 ,Andrew S·Tanenbaum 的現代作業系統 和作業系統設計與實現 等,其中作業系統設計與實現 還是 Linus 當年設計實現 Linux 核心時的主要參考。UNIX作業系統設計 和Linux核心設計與實現 也非常經典,值得一讀,Linux核心設計與實現 的作者是 Linux 核心的核心開發者,還是核心搶佔子系統的作者。自己動手寫作業系統 也可以看一下。
Linux 核心研發是一個軟硬體結合的領域,計算機組成原理和體系結構相關的知識必不可少,組合語言,CPU 的 MMU 等等都需要有所瞭解。相關的經典著作有深入理解計算機系統 、計算機組成與設計硬體/軟體介面 、ARM嵌入式系統開發 和MIPS體系結構透視 等。答住過去關注的主要硬體平臺是 ARM 的,因而關於 X86 平臺的介紹,可以自行找涵蓋了 MMU/保護模式 的 X86 組合語言有關的著作來研究。
Linux 核心開發需要的基本背景知識大概就是這些。
Linux 核心開發研究在技術上的路線圖。首先當然是從能夠快速上手,能夠快速帶來成就感的地方開始。硬體平臺可以用自己日常使用的 PC 機,裝上 Linux 發行版,安裝必要的編譯連結等開發工具,差不多就可以上手了。Linux 核心的文件非常齊全,可以用 Git 把 Linux 核心的原始碼整個下載到本地,然後編譯一下,熟悉熟悉 Linux 核心的構建系統,畢竟在整個的 Linux 核心研發過程中需要與這套系統打交道的地方很多。
就 Linux 核心研究和開發本身來說,最簡單最方便的入手點就是驅動程式了。驅動程式可以從簡單的字元裝置記憶體型驅動開始,編寫一個 “Hello world”字元裝置驅動,暴露基本的檔案操作,編譯並動態載入進核心,在通過檔案操作訪問它時,可以讓它僅僅列印一個“Hello world”。當然核心不能使用 C 語言標準庫,核心列印的資訊也不通過終端來看,而是通過 dmesg 命令來看。據說當前大多數的 Linux 核心研發工程師所做的工作,都是在搞驅動,驅動相關的程式碼在 Linux 核心程式碼中的佔比遠超一半。介紹 Linux 核心驅動的書很多,經典的長盛不衰但有點老的有Linux裝置驅動程式 ,還有Linux裝置驅動開發詳解 和精通Linux驅動程式開發 等值得一讀。實際的 Linux 核心驅動當然不可能像“Hello world”字元裝置驅動那麼簡單。實際編寫驅動時,硬體裝置本身的協議需要仔細研讀,諸如硬體裝置有幾個暫存器或者 IO 埠,對這些暫存器和 IO 埠的不同訪問方式可以訪問到什麼功能等等。此外在 Linux 核心中執行的驅動程式程式碼,與核心中的其它子系統的互動幾乎是必不可少的,因而 Linux 驅動相關的書讀下來,會發現大部分都在講核心中的記憶體分配和管理,Linux 核心中的併發同步方法等等。嵌入式 Linux 系統有關的書會講許多關於硬體訪問方法的內容,值得一讀,如嵌入式Linux應用開發完全手冊 ,ARM嵌入式系統基礎教程 ,嵌入式Linux基礎教程
很長時間沒有通過讀書來學習研究 Linux 核心,最近新出的書就不太瞭解了。不過在有了一定的基礎之後,研究 Linux 核心最好的方法就是,閱讀 Linux 核心官方相關模組的文件說明,閱讀 Linux 核心的程式碼,然後做一些除錯了。
研究學習 Linux 核心,除了從驅動入手外,也可以從另外兩個點入手,一是核心的啟動過程,二是系統呼叫。核心啟動和系統呼叫也都是離使用者最近的點,相對比較容易我們著手分析除錯。
能夠上手寫一些 Linux 核心程式碼,並對 Linux 核心開發中能夠用到的工具,如 Linux 核心提供的同步的函式,記憶體分配管理的函式等基礎有所瞭解之後,就可以根據自己的喜好和專案需要,來具體深入學習研究特定子系統了,如任務排程,記憶體管理,檔案系統和網路等等。
總結一下,Linux 核心開發研究在技術上的路線圖大概是這樣的:程式碼下載和構建 -> 選擇從 Linux 驅動、核心的啟動過程或系統呼叫三者之一入手開始自己的核心開發之旅 -> 學習 Linux 核心開發中能用到的工具和函式庫 -> 根據工作和專案需要,選擇某個自己感興趣的子系統,如任務排程,記憶體管理,檔案系統、IO、裝置驅動和網路等等深入研究,完成自己的工作。
Linux 核心開發過程中的分析除錯手法。硬體平臺可以用自己的 PC 機,裝上 Linux 發行版,然後在上面做實驗。也可以用 ARM 平臺做為硬體平臺,可以買一塊 ARM 開發板或者 Google 的 Nexus 系列手機。用 Google 的 Nexus 系列手機時,可以參考 Google 提供的官方文件來構建核心。不用硬體,用模擬器或虛擬機器更方便,還不用擔心把電腦或手機變成磚。Android 模擬器用來研究 Linux 核心非常方便。分析除錯可以通過打斷點或者列印日誌來做。用 Android 模擬器來打核心的斷點比較方便。
最後,樂者為王 是一本介紹 Linus 的書,非常有意思。關於 Unix 社群的一些文化和哲學有關的內容可以經常看一下。