寫在前面
無意間我看到 Dave Jones 寫給 kernel 新手的這篇文章(Dove Jones 是 red hat 公司 Fedora Kernel team 的 leader,也參與過不少計畫與專案),覺得很有意思,也頗為受用。於是就乾脆把他翻成中文,給想要研究 Linux Kernel 的入門者與我自己,作為參考。先聲明我並不是專業的翻譯,若有錯誤還請輕虐(跪)!另外有些字詞我刻意保持原文,諸如 kernel, hack, userspace。因為這些詞彙若翻成中文很容易混淆其意義。
以下為內容
該從何處下手?
許多想成為 Kernel Hacker 的人經常會問我,如何仰賴管理 Fedora Kernel 為工作過活。
其中一句我最常聽到的話是:『 Kernel 如此的龐大,怎麼可能任何人都可能明白所有內容呢?』事實是,只有極少數人真正了解整個 Kernel。大部分有名的 Kernel Hacker 有今日的成就,是因為他們專注於一件事,一個分支。當然一定也有例外,某些人好比 Andrew Morton,Alan Cox 和 Linus 就是『全能手』(譯註: All-rounder 是指在板球比賽中可以擔任所有位置的全能手),他們幾乎 hacked kernel 所有部份。許多人喜歡那樣的超級英雄。但成為一個專注於特定領域的專家,並沒有什麼不對。
無論是全能手或是領域專家都有一個共通點,他就是理解共同的 Kernel APIs。像是如何分配/釋放記憶體,如何建立 PROC/sysfs 檔案。大部分『我該如何……』之類的問題,你都可以看看 Kernel 的其他部份是如何針對類似情況去實作,因而找到答案。當對使用 Kernel APIs 有了足夠的經驗,你也已經學會一些高階的概念,像是『如何撰寫不瞎的使用者界面』。
對於學習 Kernel hacking 並沒有捷徑。它歸結為你在研讀與理解程式碼投資的時間,從你犯的錯誤中學習,尤其重要的是,最終你將領悟到,它只是程式碼。在 kernel hacking 過程中可能有一些附加的限制,讓你想要逃回到 userspace,但一旦你掌握了基礎知識,將越來越得心應手。
基礎:
- 在你作任何進一步的動作之前,確認你已經了解如何編譯與安裝 kernel
- C 語言的知識是很重要的。如果你對指標邏輯或其他概念覺得很吃力,請在 userspace 下多加努力,直到你更了解如何使用。因為你錯誤的認知導致程式在 userspace 中崩潰,遠比在 kernel 中發生錯誤來容易揪錯,理解,與學習。因為後者只會讓你的系統鎖住或是重置而已。
必讀工具:
首要:
- K&R 的 The C programming language 是 C 語言書籍中的聖經。如果你對於指標邏輯,巢狀結構,和其他C語言的觀念沒有深厚的基礎,從這本書先開始下手。(在這個階段,你應該多花點時間在 userspace 使用 C。直到你已經很習慣之前,都不應該進入 kernel。 userspace 對於錯誤的容忍度是相對的高出很多)
- 理解各種資料結構如串列,樹狀,等等是相當重要的。Introduction to algorithms 是你這階段的指導書。
Kernel書籍:
市面上已經有許多關於 kernel hacking 的好書。由於 Linux 發展快速,現在看來他們已經過時了。即便如此,他們某些部份還是有閱讀價值的。像是良好的基本概念說明,與開發歷程等都可以成為實用的知識。
- Linux Kernel Development (3rd Edition)
- Linux Kernel in a Nutshell (In a Nutshell (O’Reilly))
- Linux Device Drivers, 3rd Edition
- 即使這幾本著重在 userspace, Linux System Programming: Talking Directly to the Kernel 和 C Library and The Linux Programming Interface: A Linux and UNIX System Programming Handbook 都是很有閱讀價值的。
其他資源:
- kernelnewbies 對於入門者是個很好的資源。 這裡包含大量的範例,與指標。
- Jonathan Corbet 也寫了一個很棒網站 lwn.net 每週都會寫下前一週 kernel 開發的簡要重點。這非常值得研讀,即便你是關注於一些變動和說明,有時候一個簡要的敘述比起閱讀兩百封 Email 討論串來得好的許多。
- Linux Kernel 程式碼 Documentation 目錄包含為數不少的實用文件,值得花時間好好閱讀。
- 最後,程式碼本身程式碼本身。找到你感興趣的部份,找出他是 kernel 哪一部分處理的,然後便從該處下手。
實用工具:
- `grep -r` 的重要性無可言喻。
- 你將會經常的編譯再編譯,那麼就安裝 ‘ccache’吧。 大多數的發版本在安裝時已經自動幫你安裝此套件。如果你在本地端有數台電腦想要做分散式編譯,那麼 ‘distcc’ 就是你在尋找的!(註:常用的作法是,放置你的 ~/.ccache 目錄在最快的裝置,像是 SSD)
- 無論你是使用 emacs 或是 vi,’ctags’ 在搜尋程式碼方面相當實用。在 kernel 程式碼的根目錄執行 ‘make ctag’ 可以產生索引。你可以學習如何使用你最愛的編輯器做搜尋。(vi 中,在一個函式名稱上執行 ctrl-] 即可跳到該函式,執行 ctrl-t 即可返回。:ts 可以讓你在不同搜尋結果中切換。你也可以在命令列執行 vim -t functionname)
- 有些人覺得 cscope 在某些地方相當好用。執行 ‘make cscope’ 產生索引。執行 ‘cscope’ 進入一個界面可以尋找你所使用/定義的函式。
“我不知道該 hack 什麼!”
一個好的方式可以使用你剛學習到的技能就是看看 kernel 臭蟲追蹤的 the open bugs,找你感興趣的東西,並且試著幫忙修復。即便許多驅動程式的臭蟲需要有相依的硬體做除錯/測試,還是有很多的問題可以但純從程式碼去解決。那裡永遠不缺乏新的臭蟲,且透過臭蟲修復可以學習到 kernel 中不同部份是如何相互運作的。同時,我每週都會發布 Fedora kernel 的臭蟲報告。
“我真的無法了解”
不是每個人都可以成為太空人,搖滾巨星,或是 kernel hacker。這是件好事。真的!還有許多事都可以協助到 Linux。
- 測試。儘管 kernel hacking 不是你的事,如果你總是喜歡嘗鮮,編譯和測試最新的 Linus 或是 Andrew 的版本總是很有幫助。如果它發生問題了,很好!你可以發布一些訊息在 linux-kernel 臭蟲回報上!
- 測試相關。撰寫測試工具。新的系統呼叫(system call)被加入 kernel?很好,撰寫一些應用程式盡可能的從各方面呼叫他!然後在他發生問題時大聲抱怨!部份極簡單的測試工具對我們來說卻是最有幫助的。檔案系統壓力測試工具 fsx 他已經成為檔案系統開發人員不可或缺的工具。我自己的 Trinity 專案經常在每一個釋出週期發現臭蟲。如果多幾個像這樣的工具就太完美了!
- Hacking userspace 並不是很遜的事。userspace 尚有太多太多太多的東西需要熱愛他的人去完成。發掘一些東西是讓你覺得不好用的,然後解決他。如果不能解決,與他的作者參與討論與寫作,也許他們可以給你一些看法。部份大型的專案像是 xorg 真的需要一些 hacker。 (就我的看法,如果你愛好與硬體相關的工作如驅動程序,基於易於偵錯的因素, X 是一個比 kernel 更好的出發點。)
- 分類工作。Bugzilla 被臭蟲淹沒(包括上游的 kernel.org 和 Fedora)。他們之中有許多已經不合時宜或是在現行版本中被修復了。沒有人有足夠的時間定期地去尋找從未被採納的補丁,關閉重複的報告,聯絡回報者等。現在就加入吧!
- 文件。如果在你的學習歷程中,發現有什麼特別難以理解的,並且沒有文件說明它。這將是一個機會讓你你成為文件撰寫的超級英雄!基於一些奇怪的因素,kernel hacker 討厭撰寫文件。
“關於 janitor 任務?”
雖然 janitor 專案還是有一些有用的資訊,但學習補丁並不是真一個好的學習方式。而且那些補丁除了讓程式碼符合撰寫風格和其他瑣碎的事情之外,什麼都沒做。沒有人真的需要學習修改函式名稱的技巧。學習那些被建議的規則並且使用他們,而不是專注於在那些規則上。
當我得到一些新的問題或新的想法可以作為人們學習的方向時,我會定期加入到本頁面。如果你有關於 Linux kernel hacking 的問題,請隨時發電子郵件給我,我會嘗試你指引你正確的方向。我真的沒有時間來幫你崩潰的代碼除錯,但對於更高層次的問題,即使我無法幫你,至少我還大概知道誰可以。
通告: Linux-main.c內的函式命名方式 – Gavin's Blog