內核開發常識收錄

譯者:張樂 robert_AT_thizlinux_DOT_com
原作:Greg KH
譯註:本文依據take 3翻譯,應該不會再有大的改動了,如果有本文會隨時更新
     時間倉促,恐難免錯漏,歡迎指正
譯文:

------------------------------

HOWTO do Linux kernel development
---------------------------------

這篇文章將是這個話題的最權威的文檔。它將教你如何成爲一個Linux內核開發者以及學會如何和Linux內核社區一起工作。它不包含任何有關內核編程的技術細節,但是會幫你在這方面指明方向。

如果這篇文檔裏任何部分已經過時,請把補丁發送給本文的維護者,他的聯繫方式列在本文檔的末尾。

介紹
---

好了,你想成知道如何成爲一個Linux內核開發者麼?或者你的老闆告訴你,“去爲這個設備寫一個Linux驅動。“這篇文檔的目的,就是通過描述你需要經歷的過程和提示你如何和社區一起工作,來教給你爲達到這些目的所需要知道的所有知識。本文也嘗試解釋社區爲什麼這樣工作的一些原因。

內核幾乎全是用C寫成的,有一些架構相關的部分是用彙編語言寫成的。熟練掌握C語言是內核開發的必備條件。彙編語言(任何架構)的瞭解不是必須的,除非你準備做某個架構的底層開發。雖然下面這些書不能完全代替紮實的C語言教學和/或者成年累月的經驗,他們還是不錯的參考,如果用得着的話:
 - "The C Programming Language" 作者: Kernighan and Ritchie [Prentice Hall]
 - "Practical C Programming" 作者: Steve Oualline [O'Reilly]


內核是用 GNU C 和 GNU 工具鏈寫成的。雖然它符合 ISO C89 標準,它還是使用了一些標準中沒有的擴展。內核是自稱體系的 C 環境,它並不依賴標準C庫,所以某些C語言標準是不支持的。任意長度long long類型除法和浮點數是不被允許的。有時候會很難理解內核對於它所使用的工具鏈和擴展的假定,而且不幸的是也沒有關於它們的絕對的參考。請查閱gcc的info頁(`info gcc`)以獲取有關信息。

請記住你是在嘗試學習如何與已經存在的開發社區一起工作。這是一羣成分複雜的人們,他們對於代碼,風格和步驟有高的標準。這些標準是經過時間檢驗的。他們發現遵循這些標準對於這樣一個大規模的且地理上分散的團隊是最佳的選擇。嘗試提前學習儘可能多的有關這些標準的知識,因爲它們都有很好的文檔;不要期望別人會遵照你或者你公司的行事方式。

法律問題
------

Linux內核源代碼依照GPL發佈。請參考源代碼樹下的COPYING文件,以獲取有關這個許可證的詳細信息。如果你對這個許可證有疑問,請聯繫你的律師,不要在Linux內核郵件列表裏詢問。郵件列表裏的人們不是律師,你不應該依賴於他們對於法律問題的解釋。

欲瞭解有關GPL的常見問題和答案,請看:
    http://www.gnu.org/licenses/gpl-faq.html

文檔
---

Linux 內核源代碼樹有很多文檔,它們對於學習如何與內核社區交流來說有不可估量的價值。當新的功能加進內核的時候,通常建議作者把解釋這個新功能的文檔也加進內核。如果一個內核變動導致了內核對用戶空間界面的改變,建議你把這個信息或者一個解釋了這個變動的manpage的補丁發送給手冊頁的維護者 mtk- [email protected]

這裏有一個內核源代碼樹裏需要閱讀的文件列表:
  README
    這個文件簡單介紹了Linux內核的背景,並描述了配置和編譯內核需要做哪些事情。內核新手應該從這裏開始。

  Documentation/Changes
    這個文件介紹了成功編譯和運行內核所需要各種不同軟件的列表。

  Documentation/CodingStyle
    這個文件描述了Linux內核代碼風格,還有背後的一些原因。所有的新代碼的要符合這個文檔裏的準則。大多數維護者只會接受符合這些規則的補丁,很多人只看符合正確風格的代碼。

  Documentation/SubmittingPatches
  Documentation/SubmittingDrivers
    這些文件非常詳細的介紹瞭如何成功的創建和發送一個補丁,包括(但不限於):
      -Email內容
      -Email格式
      -發送給誰
    遵守所有這些規則並不能保證成功(對所有的補丁都需要進行內容和風格的詳細檢查),但是不遵守這些規則就一定不會成功。

    其他關於如何創建補丁的很好的文章有:
    “The Perfect Patch"
        http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt
    "Linux kernle patch submission format"
        http://linux.yyz.us/patch-format.html

  Documentation/stable_api_nonsense.txt
    這個文件解釋了有意識的決定-不在內核裏使用穩定的API-的原因,包括:
      -子系統分隔層(爲了兼容?)
      -操作系統之間的驅動可移植性
      -緩和(或者阻止)內核源代碼樹的急速變動
    這個文檔對於瞭解Linux的開發哲學是非常關鍵的,對於由開發其他操作系統轉而開發Linux人也是很重要的。

  Documentation/SecurityBugs
    如果你感覺到你發現了Linux內核裏的一個安全問題,請遵照這個文檔裏所描述的步驟來提醒內核開發者,並幫助解決問題。

  Documentation/ManagementStyle
    這個文檔描述了Linux內核維護者如何運作,以及他們爲什麼這樣做。它對於任何內核開發新手(或者任何對本話題感興趣的人)來說是非常重要的。因爲它解釋了一些慣有的錯誤概念,可解決有關內核維護者獨特行爲的疑惑。

  Documentation/stable_kernel_rules.txt
    本文件描述了穩定版本內核釋出的規則,還有如果你想對其中的一個版本做一些改動應該做些什麼。

  Documentation/kernel-docs.txt
    一個有關內核開發的外部文檔的列表。如果你在內核內部文檔裏沒有找到你要找的東西,你可以參考這個列表。

  Documentation/applying-patches.txt
    介紹了對於什麼是補丁,以及如何應用補丁於不同的內核開發分支。

內核也有很多可以從源代碼自動產生的文檔。這包括內核內部API的全面描述,有關如何處理好鎖定的規則。這些文檔會被創建於 Documentation/DocBook/文件夾中。在內核主源碼樹中通過運行下面的命令可以創建出PDF,Postscript,HTML和 manpage等不同格式的文檔:
    make pdfdocs
    make psdocs
    make htmldocs
    make mandocs

成爲一個內核開發者
--------------

如果你對Linux內核開發一無所知,你可以看看Linux KernelNewbies項目:
    http://kernelnewbies.org
它包含一個郵件列表,在那裏你可以問任何有關內核開發的基礎問題(在問問題之前先搜索一下存檔,很可能這個問題已經被解答過了。)它還有一個IRC頻道,你可以在裏面實時的提問。它還有很多有用的文檔,對於學習Linux內核開發很有用。

這個網站有有關代碼組織,子系統,當前項目(代碼樹之內的和之外的)的基本信息。它也描述了一些基本的“物流”信息,比如怎麼樣編譯內核和怎麼樣打補丁。

如果你不知道從何處起步,但是你想找一些任務來做以加入內核開發社區,請看一下Linux Kernel Janitor項目:
    http://janitor.kernelnewbies.org/
這是一個很好的起步的地方。它描述了一些相對來說簡單的內核中需要清理的和解決的問題。和負責這個項目的開發者一起工作,你會學到如何令你的補丁進入Linux內核樹的基本知識,而且可能會爲你指明下一步的發展方向,如果你自己尚不明確的話。

如果你已經有了一段代碼想要放到內核樹裏,但是需要某種形式的幫助,那麼kernel-mentors項目就可以幫你的忙了。這是一個郵件列表,可以在下面找到:
    http://selenic.com/mailman/listinfo/kernel-mentors

在你對Linux內核代碼作任何實際的改動之前,必須要了解相關的代碼是如何工作的。爲了達到這個目的,沒有比直接讀它(很多困難的地方都有很好的註釋)更好的方法了,甚至可能是在某個特殊工具的幫助下來閱讀。很值得推薦的這樣一種工具是Linux Cross-Reference項目,它可以把源代碼以一種自我引用的、索引的網頁形式顯示出來。一個非常好的最新的內核代碼倉庫可以在這裏找到:
    http://sosdg.org/~coywolf/lxr

開發流程
------

Linux內核開發流程當前包括一些主內核分支,和很多不同的子系統專有的內核分支。它們是:
  - 主 2.6.x 內核樹
  - 2.6.x.y -stable 內核樹
  - 2.6.x -git 內核補丁
  - 2.6.x -mm 內核補丁
  - 子系統專有內核樹和補丁

2.6.x 內核樹
-----------
2.6.x 內核樹是有Linus Torvalds維護的,可以在kernel.org的pub/linux/kernel/v2.6目錄裏找到。它的開發流程是這樣的:
   - 當一個新的內核發佈之後,一個爲期兩個星期的窗口打開,在這段時間裏維護者可以提交大的補丁給Linus,通常是已經在-mm內核中存在了一定時間的補丁。推薦的提交補丁的方式是通過git(有關git的更多信息可以在http://git.or.cz/找到),但是普通的補丁也是可以的
   - 兩個星期之後一個-rc1內核發佈,然後現在只可以再加入不會爲內核添加新功能的補丁,因爲那樣的補丁可能會影響這個內核的穩定性。請注意這個時候一個整的新驅動(或者文件系統)可以被接受。因爲只要這個變動是自成一體的並且不影響它之外的代碼的話,就不會有產生迴歸的危險。在-rc1發佈之後, git可以用來發送補丁給Linus,但是這些補丁也需要發到一個公開的郵件列表裏以備審查。
  - 當Linus確信當前的git(內核代碼管理工具)樹已經處於一個合理的健全狀態,足夠測試時,一個新的-rc就會發布了。目標是每週發佈一個新的-rc內核。
  - 這個過程將會持續到內核被認爲可以發佈爲止,整個流程會持續大概6個星期。

Andrew Morton在linux-kernel郵件列表裏寫的有關內核發佈的一句話值得提一下:
    “沒有人知道什麼時候一個內核會發布,因爲它發佈的依據已經掌握的bug狀態,而不是事先設想好的一個時間線。“

2.6.x.y -stable 內核樹
---------------------

有四個數字版本號的內核是-stable內核。他們包含一些相對較小的和重要的修正。這些修正針對的是在一個給定2.6.x內核中發現的安全問題或者重大的迴歸。

對於想使用最新的穩定內核並且對於幫助測試開發/實驗版本不感興趣的用戶,這是推薦使用的版本。

如果沒有2.6.x.y版本,那麼最高版本號的2.6.x內核是當前穩定內核。

2.6.x.y由“stable”團隊<[email protected]>維護,每週發佈一次。

內核樹裏的文件Documentation/stable_kernel_rules.txt描述了什麼樣的改動可以被-stable樹所接受,以及發佈流程是怎樣工作的。

2.6.x -git 補丁
--------------
這些是在git倉庫裏管理的Linus內核樹的每日快照。這些補丁每天發佈一次,代表Linus樹的當前狀態。它們比-rc內核更具實驗性質,因爲它們是自動生成的,以至沒有人曾經瞟上一眼來檢查它們是否處於健全狀態。

2.6.x -mm 內核補丁
----------------
這些是Andrew Morton發佈的實驗性質的內核補丁。Andrew取得所有不同子系統的內核樹和補丁,連同從linux-kernel郵件列表里拉過來的補丁,把它們融合在一起。這個樹是新功能和補丁證明自己的場所。如果一個補丁在-mm裏證實了自己的價值,Andrew或者子系統維護者就會把它提交給Linus,以求被收錄於主線內核中。

強烈建議所有的新補丁在發送給Linus之前都先發到-mm樹裏測試一下。

打了此種補丁的內核不適用於追求穩定的系統中,運行它們比運行其他任何分支都更具冒險性。

如果你想幫助內核開發流程,請測試並使用這些內核發佈,並在linux-kernel郵件列表裏提供回饋,如果你發現任何問題的話,哪怕什麼問題也沒有。

在所有其他實驗性質的補丁之外,這些內核補丁通常還會包含在發佈時在主線-git內核中已經包含的改動。

-mm內核沒有一個固定的發佈計劃,但是通常在每兩個-rc內核發佈間歇期會發布一些-mm內核(1到3個都很常見)。

子系統專有內核樹和補丁
-----------------
一些不同的內核子系統開發者公佈他們的開發樹,這樣其他人可以看到在內核的不同領域裏正在發生什麼。這些樹都會被包含在-mm內核發佈中。

下面是一些不同的內核樹的列表:
  git樹:
    - Kbuild 開發樹, Sam Ravnborg <[email protected]>
    kernel.org:/pub/scm/linux/kernel/git/sam/kbuild.git

    - ACPI 開發樹, Len Brown <[email protected]>
    kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git

    - 塊設備開發樹, Jens Axboe <[email protected]>
    kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git

    - DRM 開發樹, Dave Airlie <[email protected]>
    kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git

    - ia64 開發樹, Tony Luck <[email protected]>
    kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git

    - ieee1394 開發樹, Jody McIntyre <[email protected]>
    kernel.org:/pub/scm/linux/kernel/git/scjody/ieee1394.git

    - infiniband, Roland Dreier <[email protected]>
    kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git

    - libata, Jeff Garzik <[email protected]>
    kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git

    - 網絡驅動, Jeff Garzik <[email protected]>
    kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git

    - pcmcia, Dominik Brodowski <[email protected]>
    kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git

    - SCSI, James Bottomley <[email protected]>
    kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git

  其他git內核樹可以在http://kernel.org/git找到

  quilt trees:
    - USB, PCI, Driver Core, and I2C, Greg Kroah-Hartman <[email protected]>
    kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/

報告Bug
------

bugzilla.kernel.org是Linux內核開發者追蹤內核bug的地方。我們鼓勵用戶在這個工具中報告他們發現的所有bug。欲知使用內核bugzilla的具體細節,請看:
    http://test.kernel.org/bugzilla/faq.html

主內核源碼目錄中的REPORTING-BUGS文件有一個報告可能有的內核bug的模板,並詳細講述了內核開發者需要什麼樣的信息,以便他們可追蹤到問題所在。

郵件列表
------

就像上面的一些文檔所描述的,大多數核心內核開發者參與Linux內核郵件列表的討論。如何訂閱和取消訂閱這個列表的細節可以從這裏找到:
    http://vger.kernel.org/vger-lists.html#linux-kernel
網上很多地方都有這個郵件列表的存檔。使用一個搜索引擎來搜索這些存檔。比如:
    http://dir.gmane.org/gmane.linux.kernel
強烈建議你在向列表發郵件詢問之前,先在存檔中搜索一下你想問的話題。很多事情都已經詳細的討論過了,它們只在郵件列表存檔中有記錄。

很多內核子系統也有它們單獨的郵件列表,在那裏開發者們做他們的開發工作。請查看MAINTAINER文件來找到這些不同子系統的郵件列表。

很多郵件列表放置於kernel.org之上。有關它們的信息可以在這裏找到:
    http://vger.kernel.org/vger-lists.html

請記住在使用這些列表時請遵守良好的行爲習慣。下面的URL有一些如何在郵件列表上與人交流的簡單的準則,雖然有一點俗氣:
    http://www.albion.com/netiquette

如果有許多人回覆你的郵件,收件人的抄送列表會變得很長。在沒有一個合理的理由時不要把任何人從抄送列表中去掉,或者不要只回覆被列出的地址。要對於收到同一封信兩次感到習慣,一次從發信者,一次從郵件列表。不要爲了好看而加上別緻的郵件頭部,人們不喜歡這樣。

記得保證你的回覆的上下文和屬性的完整性,在你的回覆的最上方保留類似“John Kernelhacker wrote ...“的字樣,把你的回覆寫在被引用的段落之間,而不要寫在郵件的最上方。

如果你在你的郵件里加入了補丁,要確保它們是純文本,就想Documentation/SubmittingPatches裏所說的。內核開發者不希望處理附件或者壓縮的補丁;他們會希望評價你的補丁的每一行,只有純文本才符合這個要求。確保你使用的郵件客戶端軟件不會破壞空格和製表符。你可以發一個郵件給你自己,然後應用你自己的補丁來先做個測試。如果不行,修復你的郵件程序或者換一個。

最重要的一點,請記得顯示出你對其他訂閱者的尊重。

和社區一起工作
-----------

內核社區的目標是提供可能提供的最好的內核。當你提交了一個補丁等待被收錄時,它會被且僅被該領域的技術權威所檢查。所以,你應該期待什麼呢?
  - 批評
  - 評論
  - 被要求改動
  - 被要求解釋
  - 沉默

記住,這是讓你的補丁進入內核的一部分。你必須能夠接受對你的補丁的批評和評論,在技術的層面上評估它,然後要麼對你的補丁作出修改,要麼提供清晰而言簡意賅的理由解釋爲什麼不應該做改動。如果沒有對你的補丁的回覆,等幾天再試一次,有時候在流量很大的時候信件可能丟失,或被人忽略遺忘了。

你不應該做什麼:
  - 期待你的補丁沒有任何疑問的被接受
  - 不接受批評,不承認缺點
  - 忽略評論
  - 在不做任何修改的情況下再次提交補丁

在一個尋找可能存在的最好的技術解決方案的社區裏,關於一個補丁怎樣的有用必定會存在不同的意見。你應該採取合作的態度,願意改變你的意見以適應內核的需要。或者至少願意證明的你的觀點有價值。記住,犯錯誤是可以接受的,只要你願意朝着正確的解決方案努力。

如果對於你的第一個補丁的迴應只是一些要求你改正的意見,這很正常。這並不意味着你的補丁將不會被接受,這些意見也不是針對你本人的。你要做的只是改正你的補丁然後重新發送。

內核社區和企業架構的區別
-------------------

內核社區和大多數傳統的企業開發環境工作形式不一樣。這裏有一個列表你可以嘗試遵照執行以避免出現問題:
  關於你提交的補丁的好的說法:
    - “這個可以解決多個問題。”
    - “這個刪除了2000行代碼。”
    - “這個補丁解釋了我嘗試想描述的東西。”
    - “我在5個不同的架構上測試了它……”
    - “這裏是一系列的小補丁,它們可以……”
    - “這個在典型的機器上可以提高表現……”

  你應該避免的壞的說法:
    - “我們在AIX/ptx/Solaris上都是這樣做的,所以它一定是好的……”
    - “我已經這樣做20年了,所以……”
    - “我的公司需要這樣做來掙錢”
    - “這是我的一千頁的設計文檔,它解釋了我的想法”
    - “我已經在它上面花了6個月的心血……”
    - “這裏是一個5000行的補丁,它……”
    - “我重新寫了所有現有的垃圾,在這裏……”
    - “我有完成期限,這個補丁必須現在被應用。”

內核社區和大多數傳統軟件工程工作環境的另一個不同是沒有面對面的交流。使用email和irc作爲主要交流形式的好處之一是不會存在基於性別或者種族的歧視。Linux內核工作環境接受女士和少數民族,因爲你的存在只是一個email地址。國際化也幫助我們實現了平等的工作環境,因爲你無法根據一個人的名字來判斷一個人的性別。一個男人可以叫Andrea,一個女人可以叫Pat。大多數爲Linux內核做過工作或者發表過觀點的女性對此都深有體會。

對於不習慣英語的人來說語言障礙可能會導致一些問題。對於語言的良好的掌握可以令思想在郵件列表上交流的更暢通,所以建議你在發送郵件之前檢查一下你的郵件內容在英語裏是否有意義。

打散你的補丁
---------

Linux 內核社區不樂意接受大段的代碼,一般會在收到時立刻丟棄。你的補丁需要適當的被介紹,討論,並打散爲細小的,獨立的片段。這幾乎和公司裏經常做的完全背道而馳。你的提議必須在開發流程的早期提出,這樣你纔可以收到足夠的關於你的工作的回饋。這也會令社區感覺到你是在和他們一起工作,而不是利用他們作爲傾倒你的補丁的場所。但是,請不要一次向郵件列表發送超過50封email,你的一系列補丁的個數應該永遠小於這個數字。

把補丁打散的理由如下:

1)  小的補丁增加了你的補丁被應用的機會,因爲它不需要花太多的時間和精力來檢查        它的正確性。一個5行的補丁,一個維護者只要花一秒鐘瞟一眼然後就可以應用了。不過,一個500行的補丁需要一個小時來檢查是否有錯誤(所需的時間跟補丁的大小差不多成指數級別增長)。
   
   小補丁也使得在出錯的時候很容易debug。如果出了問題,小補丁可以一個一個的取消,大補丁就比較麻煩了。

2) 除了要把補丁打散之外,在提交之前還要重寫和簡化(或者只是簡單的重排序)你的補丁。這一點也是很重要的。

這裏有一個內核開發者Al Viro所做的類比:
    “想一下一個老師爲一個數學系學生批改作業的情景。老師不希望看到學生在回答出正確答案之前的嘗試和失敗。他們想看到最清楚的,最優美的答案。一個好學生了解這一點,並不會在得到最終答案之前把他們的中間結果提交上去。

    對於內核開發來說同樣是這樣。維護者和評論者不希望看到問題的解決方案背後的思考過程。他們想看到一個簡單和優美的解決方案。”

提供一個優美的解決方案和同社區一起工作討論你未完成的作品,要維持此二者之間的平衡可能是一個很有挑戰性的事情。所以應及早的參與一個開發流程以獲得回饋來改進你的作品,但仍要保證你的補丁的小塊頭,這樣它們可能提早被接受,哪怕是在你的整個作品還爲完成時。

也請注意,如果你的補丁尚未完成而且還需要修改,請不要提交。

證明你的改動
---------

除了打散你的補丁之外,讓Linux社區理解爲什麼他們要加入這項改動也是很重要的。新的功能必須要被證實它們需要而且有用。

爲你的改動寫文檔
-------------

在你提交補丁時,要格外留心你在email裏說的話。這些信息將會成爲這個補丁的ChangeLog信息,將會被保留從而使每個人任何時候都可以看到。它必須完整的描述這個補丁,包括:
  - 爲什麼這個改動是需要的
  - 這個補丁的整體設計方案
  - 實現細節
  - 測試結果

欲知這個過程到底看起來是什麼樣子的,請看這個文檔的ChangeLog部分:
  “The Perfect Patch”
      http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt




所有這些事情有時候很難做到。要想完美做到這些要求可能需要幾年的時間。這是一個持續的發展過程,需要很多耐心和決心。但是不要放棄,這是可以實現的。很多人已經做到了這一點,每個人都經歷過你現在這個階段。



-------------
感謝Paolo Ciarrocchi允許我在他所寫的文章的基礎上寫成本文的“開發流程”部分,感謝Randy Dunlap和 Gerrit Huizenga爲了他們應該說的和不該說的一些事情。也感謝Pat Mochel, Hanna Linder,  Randy Dunlap, Kay Sievers, Vojtech Pavlik, Jan Kara, Josh Boyer, Kees Cook,  Andrew Morton, Andi Kleen, Vadim Lobanov, Jesper Juhl, Adrian Bunk, Keri Harris,  Frans Pop,David A. Wheeler, Junio Hamano, Michael Kerrisk, 和  Alex Shepard爲了他們對於本文初稿的評論和意見。



維護者: Greg Kroah-Hartman <[email protected]>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章