.. SPDX-License-Identifier: GPL-2.0

.. include:: ../disclaimer-zh_TW.rst

:Original: :ref:`Documentation/process/2.Process.rst <development_process>`

:Translator:

 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>

:校譯:

 吳想成 Wu XiangCheng <bobwxc@email.cn>
 胡皓文 Hu Haowen <2023002089@link.tyut.edu.cn>
 葉宸佑 Chen-Yu Yeh <chenyou910331@gmail.com>

.. _tw_development_process:

開發流程如何進行
================

90年代早期的Linux核心開發是一件相當鬆散的事情，涉及的使用者和開發人員相對
較少。由於擁有數以百萬計的使用者羣，且每年有大約2000名開發人員參與進來，核
心因此必須發展出許多既定流程來保證開發的順利進行。要參與到流程中來，需要對
此流程的進行方式有一個紮實的理解。

總覽
----

Linux核心使用一種鬆散的、基於時間的滾動發布開發模式。每兩到三個月就會有
一個新的主要核心版本發布（作為範例，我們稱之為9.x） [1]_ ，它帶來新特性、
內部API更改等等。一個典型的版本可以包含大約13000個變更集，變更了幾十萬行
程式碼。最近的版本及其日期可以在
`維基百科 <https://en.wikipedia.org/wiki/Linux_kernel_version_history>`_
找到。

.. [1] 嚴格來說，Linux核心並不使用語意化版本編號方案，而是以9.x這一對
       數字作為一個整體來標識主要發布版本。每次發布時x會遞增，只有當x被
       認為足夠大時才會遞增9（例如，Linux 5.0是繼Linux 4.20之後發布的）。

對於每個版本的補丁合併，遵循一個相對簡單的規則。在每個開發週期的開頭，“合併
視窗”被開啟。這時，被認為足夠穩定（並且被開發社群接受）的程式碼被合併到主線內
核中。在這段時間內，新開發週期的大部分變更（以及所有主要變更）將以接近每天
1000次變更（“補丁”或“變更集”）的速度合併。

（順便說一句，值得注意的是，合併視窗期間整合的更改並不是憑空產生的；它們是經
提前收集、測試和分級的。稍後將詳細描述該過程的工作方式。）

合併視窗持續大約兩週。在這段時間結束時，Linus Torvalds將聲明視窗已關閉，並
釋放第一個“rc”核心。例如，對於目標為9.x的核心，在合併視窗結束時發生的釋放
將被稱為9.x-rc1。-rc1 版本是一個信號，表示合併新特性的時間已經過去，穩定下一
個核心的時間已經到來。

在接下來的6到10周內，只有修復問題的補丁才應該提交給主線。有時會允許更大的
更改，但這種情況很少發生；試圖在合併視窗外合併新功能的開發人員往往受不到
友好的接待。一般來說，如果您錯過了給定特性的合併視窗，最好的做法是等待下一
個開發週期。（偶爾會對未支援硬體的驅動程式進行例外；如果它們不改變已有程式碼，
則不會導致迴歸，應該可以隨時被安全地加入）。

隨著修復程式進入主線，補丁速度將隨著時間的推移而變慢。Linus大約每週發布一次
新的-rc核心；在核心被認為足夠穩定並最終發布前，一般會達到-rc6到-rc9之間。
然後，整個過程又重新開始了。

例如，這裡是5.4的開發週期進行情況（2019年）:

	==============  ==============================
	九月 15         5.3 穩定版發布
	九月 30         5.4-rc1 合併視窗關閉
	十月 6          5.4-rc2
	十月 13         5.4-rc3
	十月 20         5.4-rc4
	十月 27         5.4-rc5
	十一月 3        5.4-rc6
	十一月 10       5.4-rc7
	十一月 17       5.4-rc8
	十一月 24       5.4 穩定版發布
	==============  ==============================

開發人員如何決定何時結束開發週期並建立穩定版本？最重要的指標是以前版本的
迴歸列表。不歡迎出現任何錯誤，但是那些破壞了以前能工作的系統的錯誤被認為是
特別嚴重的。因此，導致迴歸的補丁是不受歡迎的，很可能在穩定期內刪除。

開發人員的目標是在穩定發布之前修復所有已知的迴歸。在現實世界中，這種完美是
很難實作的；在這種規模的專案中，變數太多了。需要說明的是，延遲最終版本只會
使問題變得更糟；等待下一個合併視窗的更改將變多，導致下次出現更多的迴歸錯誤。
因此，大多數核心版本都有一些已知的迴歸錯誤，不過，希望沒有一個是嚴重的。

一旦一個穩定的版本發布，它的持續維護工作就被移交給“穩定團隊”，目前由Greg
Kroah-Hartman和Sasha Levin組成。穩定團隊將使用9.x.y編號方案不定期地發布穩
定版本的更新。要合入更新版本，補丁必須（1）修復一個重要的缺陷，且（2）已經
合併到下一個開發版本主線中。核心通常會在其初始版本後的一個以上的開發週期內
收到穩定版更新。例如，5.2核心的歷史如下（2019年）：

	==============  ===============================
        七月 7 	        5.2 穩定版發布
	七月 13	        5.2.1
	七月 21	        5.2.2
	七月 26	        5.2.3
	七月 28	        5.2.4
	七月 31	        5.2.5
	...	        ...
	十月 11         5.2.21
	==============  ===============================

5.2.21是5.2版本的最終穩定更新。

有些核心被指定為“長期”核心；它們將得到更長時間的支援。當前的長期核心
版本及其維護者的列表，請參考以下連結：

	https://www.kernel.org/category/releases.html

長期支援核心的選擇純粹是維護人員是否有需求和時間來維護該版本的問題。

補丁的生命週期
--------------

補丁不會直接從開發人員的鍵盤進入主線核心。相反，有一個稍微複雜（如果有些非
正式）的過程，旨在確保對每個補丁進行品質審查，並確保每個補丁實作了一個在主
線中需要的更改。對於小的修復，這個過程可能會很快完成，，而對於較大或有爭議
的變更，可能會持續數年。許多開發人員的沮喪來自於對這個過程缺乏理解或者試圖
繞過它。

為了減少這種挫敗，本文將描述補丁如何進入核心。下面的介紹以一種較為理想化的
方式描述了這個過程。更詳細的過程將在後面的章節中介紹。

補丁通常要經歷以下階段：

- 設計。這就是補丁的真正需求——以及滿足這些需求的方式——所在。設計工作通常
  是在不涉及社群的情況下完成的，但是如果可能的話，最好是在公開的情況下完成
  這項工作；這樣可以節省很多稍後再重新設計的時間。

- 早期評審。補丁被髮布到相關的郵件列表中，列表中的開發人員會回覆他們可能有
  的任何評論。如果一切順利的話，這個過程應該會發現補丁的任何主要問題。

- 更廣泛的評審。當補丁接近準備好納入主線時，它應該被相關的子系統維護人員
  接受——儘管這種接受並不能保證補丁會一直延伸到主線。補丁將出現在維護人員的
  子系統樹中，並進入 -next 樹（如下所述）。當流程進行時，此步驟將會對補丁
  進行更廣泛的審查，並發現由於將此補丁與其他人所做的工作合併而導致的任何
  問題。

- 請注意，大多數維護人員也有日常工作，因此合併補丁可能不是他們的最優先工作。
  如果您的補丁得到了需要更改的反饋，那麼您應該進行這些更改，或者解釋為何
  不應該進行這些更改。如果您的補丁沒有評審意見，也沒有被其相應的子系統或
  驅動程式維護者接受，那麼您應該堅持不懈地將補丁更新到當前核心使其可被正常
  應用，並不斷地發送它以供審查和合併。

- 合併到主線。最終，一個成功的補丁將被合併到由Linus Torvalds管理的主線儲存庫
  中。此時可能會出現更多的評論和/或問題；對開發人員來說應對這些問題並解決
  出現的任何問題仍很重要。

- 穩定版發布。大量使用者可能受此補丁影響，因此可能再次出現新的問題。

- 長期維護。雖然開發人員在合併程式碼後可能會忘記程式碼，但這種行為往往會給
  開發社群留下不良印象。合併程式碼消除了一些維護負擔，因為其他人將修復由
  API更改引起的問題。但是，如果程式碼要長期保持可用，原始開發人員應該繼續
  為程式碼負責。

核心開發人員（或他們的僱主）犯的最大錯誤之一是試圖將流程簡化為一個“合併到
主線”步驟。這種方法總是會讓所有相關人員感到沮喪。

補丁如何進入核心
----------------

只有一個人可以將補丁合併到主線核心儲存庫中：Linus Torvalds。但是，在進入
2.6.38核心的9500多個補丁中，只有112個（大約1.3%）是由Linus自己直接選擇的。
核心專案已經發展到一個沒有一個開發人員可以在沒有支援的情況下檢查和選擇每個
補丁的規模。核心開發人員處理這種增長的方式是使用圍繞信任鏈建置的助理系統。

核心程式碼庫在邏輯上被分解為一組子系統：網路、特定體系結構支援、記憶體管理、視
頻設備等。大多數子系統都有一個指定的維護人員，其總體負責該子系統中的程式碼。
這些子系統維護者（鬆散地）是他們所管理的核心部分的“守門員”；他們（通常）
會接受一個補丁以包含到主線核心中。

子系統維護人員每個人都管理著自己版本的核心原始程式碼樹，通常（並非總是）使
用Git。Git等工具（以及Quilt或Mercurial等相關工具）允許維護人員追蹤補丁列表，
包括作者資訊和其他元資料。在任何給定的時間，維護人員都可以確定他或她的儲存
庫中的哪些補丁在主線中找不到。

當合併視窗開啟時，頂級維護人員將要求Linus從儲存庫中“拉出”他們為合併選擇
的補丁。如果Linus同意，補丁流將流向他的儲存庫，成為主線核心的一部分。
Linus對拉取中接收到的特定補丁的關注程度各不相同。很明顯，有時他看起來很
關注。但是一般來說，Linus相信子系統維護人員不會向上遊發送壞補丁。

子系統維護人員反過來也可以從其他維護人員那裡獲取補丁。例如，網路樹是由首先
在專用於網路設備驅動程式、無線網路等的樹中積累的補丁建置的。此儲存鏈可以
任意長，但很少超過兩個或三個連結。由於鏈中的每個維護者都信任那些管理較低
級別樹的維護者，所以這個過程稱為“信任鏈”。

顯然，在這樣的系統中，獲取核心補丁取決於找到正確的維護者。直接向Linus發送
補丁通常不是正確的方法。

Next 樹
-------

子系統樹鏈引導補丁流到核心，但它也提出了一個有趣的問題：如果有人想查看為
下一個合併視窗準備的所有補丁怎麼辦？開發人員將感興趣的是，還有什麼其他的
更改有待解決，以瞭解是否存在需要擔心的衝突；例如，更改核心核心函式原型的
修補程式將與使用該函式舊形式的任何其他修補程式衝突。審查人員和測試人員希望
在所有這些變更到達主線核心之前，能夠存取它們的整合形式的變更。您可以從所有
相關的子系統樹中提取更改，但這將是一項複雜且容易出錯的工作。

解決方案以-next樹的形式出現，在這裡子系統樹被收集以供測試和審查。這些樹中
由Andrew Morton維護的較老的一個，被稱為“-mm”（用於記憶體管理，建立時為此）。
-mm 樹整合了一長串子系統樹中的補丁；它還包含一些旨在幫助除錯的補丁。

除此之外，-mm 還包含大量由Andrew直接選擇的補丁。這些補丁可能已經發布在郵件
列表上，或者它們可能應用於核心中未指定子系統樹的部分。同時，-mm 作為最後
手段的子系統樹；如果沒有其他明顯的路徑可以讓補丁進入主線，那麼它很可能最
終選擇-mm 樹。累積在-mm 中的各種補丁最終將被轉發到適當的子系統樹，或者直接
發送到Linus。在典型的開發週期中，大約5-10%的補丁透過-mm 進入主線。

當前-mm 補丁可在“mmotm”（-mm of the moment）目錄中找到：

        https://www.ozlabs.org/~akpm/mmotm/

然而，使用MMOTM樹可能會十分令人頭疼；它甚至可能無法編譯。

下一個週期補丁合併的主要樹是linux-next，由Mark Brown維護。根據設計
linux-next 是下一個合併視窗關閉後主線的快照。linux-next樹在Linux-kernel 和
Linux-next 郵件列表中發布，可從以下位置下載：

        https://www.kernel.org/pub/linux/kernel/next/

Linux-next 已經成為核心開發過程中不可或缺的一部分；在一個給定的合併視窗中合併
的所有補丁都應該在合併視窗開啟之前的一段時間內找到進入Linux-next 的方法。

Staging 樹
----------

核心原始程式碼樹包含drivers/staging/目錄，其中有許多驅動程式或檔案系統的子目錄
正在被添加到核心樹中。它們在仍然需要更多的修正的時候可以保留在driver/staging/
目錄中；一旦完成，就可以將它們移到核心中。這是一種追蹤不符合Linux核心編碼或
品質標準的驅動程式的方法，人們可能希望使用它們並追蹤開發。

Greg Kroah-Hartman 目前負責維護staging樹。仍需要修正的驅動程式將發送給他，
每個驅動程式在drivers/staging/中都有自己的子目錄。除了驅動程式原始檔之外，
目錄中還應該有一個TODO檔案。TODO檔案列出了驅動程式需要接受的暫停的工作，
以及驅動程式的任何補丁都應該抄送的人員列表。當前的規則要求，staging的驅動
程式必須至少正確編譯。

Staging 是一種讓新的驅動程式進入主線的相對容易的方法，它們會幸運地引起其他
開發人員的注意，並迅速改進。然而，進入staging並不是故事的結尾；staging中
沒有看到常規進展的程式碼最終將被刪除。經銷商也傾向於相對不願意使用staging驅動
程式。因此，在成為一個合適的主線驅動的路上，staging 僅是一箇中轉站。

工具
----

從上面的文字可以看出，核心開發過程在很大程度上依賴於在不同方向上聚集補丁的
能力。如果沒有適當強大的工具，整個系統將無法在任何地方正常工作。關於如何使用
這些工具的教程遠遠超出了本文件的範圍，但還是用一點篇幅介紹一些關鍵點。

到目前為止，核心社群使用的主要原始程式碼管理系統是git。Git是在自由軟體社群
中開發的許多分散式版本控制系統之一。它非常適合核心開發，因為它在處理大型儲
存庫和大量補丁時效能非常好。它也以難以學習和使用而著稱，儘管隨著時間的推移
它變得更好了。對於核心開發人員來說，對Git的某種熟悉幾乎是一種要求；即使他
們不將它用於自己的工作，他們也需要Git來跟上其他開發人員（以及主線）正在做
的事情。

現在幾乎所有的Linux發行版都打包了Git。Git主頁位於：

        https://git-scm.com/

此頁面包含了文件和教程的連結。

在不使用git的核心開發人員中，最流行的選擇幾乎肯定是Mercurial：

        http://www.seleric.com/mercurial/

Mercurial與Git共享許多特性，但它提供了一個介面，許多人覺得它更易於使用。

另一個值得了解的工具是Quilt:

        https://savannah.nongnu.org/projects/quilt

Quilt 是一個補丁管理系統，而不是原始程式碼管理系統。它不會隨著時間的推移追
蹤歷史；相反，它面向根據不斷發展的程式碼庫追蹤一組特定的更改。一些主要的子
系統維護人員使用Quilt來管理打算向上遊移動的補丁。對於某些樹的管理（例如-mm），
quilt 是最好的工具。

郵件列表
--------

大量的Linux核心開發工作是透過郵件列表完成的。如果不加入至少一個某個列表，
就很難成為社群中的一個“全功能”成員。但是，Linux郵件列表對開發人員來說也是
一個潛在的危險，他們可能會被一堆電子郵件淹沒、違反Linux列表上使用的約定，
或者兩者兼而有之。

大多數核心郵件列表都託管在kernel.org上；主列表位於：

        https://subspace.kernel.org

也有一些列表託管在別處；請查閱MAINTAINERS檔案以找到與特定子系統相關的
列表。

當然，核心開發的核心郵件列表是linux-kernel。這個列表是一個令人生畏的地方：
每天的資訊量可以達到500條，噪音很高，談話技術性很強，且參與者並不總是表現出
高度的禮貌。但是，沒有其他地方可以讓核心開發社群作為一個整體聚集在一起；
不使用此列表的開發人員將錯過重要資訊。

以下一些提示可以幫助在linux-kernel生存：

- 將郵件轉移到單獨的資料夾，而不是主信箱資料夾。我們必須能夠持續地忽略洪流。

- 不要試圖跟上每一次談話——沒人會這樣。重要的是要篩選感興趣的主題（但請注意
  長時間的對話可能會偏離原來的主題，儘管未改變電子郵件的主題）和參與的人。

- 不要回復挑事的人。如果有人試圖激起憤怒，請忽略他們。

- 當回覆Linux核心電子郵件（或其他列表上的電子郵件）時，請為所有相關人員保留
  Cc: 抄送頭。如果沒有確實的理由（如明確的請求），則不應刪除收件人。一定要
  確保你要回復的人在抄送列表中。這個慣例也使你不必在回覆郵件時明確要求被抄送。

- 在提出問題之前，搜索列表存檔（和整個網路）。有些開發人員可能會對那些顯然
  沒有完成家庭作業的人感到不耐煩。

- 避免頂部回覆（把你的答案放在你要回復的引文上面的做法）。這會讓你的回答更難
  理解，印象也很差。

- 在正確的郵件列表發問。linux-kernel 可能是通用的討論場所，但它不是尋找所有
  子系統開發人員的最佳場所。

最後一點——找到正確的郵件列表——是開發人員常出錯的地方。在linux-kernel上提出
與網路相關的問題的人幾乎肯定會收到一個禮貌的建議，轉到netdev列表上提出，因
為這是大多數網路開發人員經常出現的列表。還有其他列表可用於scsi、
video4linux、ide、filesystem等子系統。查找郵件列表的最佳位置是與核心原始程
式碼一起打包的MAINTAINERS檔案。

開始核心開發
------------

關於如何開始核心開發過程的問題很常見——個人和公司皆然。同樣常見的是失誤，這
使得關係的開始比本應的更困難。

公司通常希望聘請知名的開發人員來啟動開發團隊。實際上，這是一種有效的技術。
但它也往往是昂貴的，而且對增加有經驗的核心開發人員的數量沒有多大幫助。考
慮到時間投入，可以讓內部開發人員加快Linux核心的開發速度。利用這段時間可以
讓僱主擁有一批既瞭解核心又瞭解公司的開發人員，還可以幫助培訓其他人。從中期
來看，這通常是更有利可圖的方法。

可以理解的是，單個開發人員往往對起步感到茫然。從一個大型專案開始可能會很
嚇人；人們往往想先用一些較小的東西來試試水。由此，一些開發人員開始建立修補
拼寫錯誤或輕微編碼風格問題的補丁。不幸的是，這樣的補丁會產生一定程度的噪音，
這會分散整個開發社群的注意力，因此，它們越來越被人不看重。希望向社群介紹
自己的新開發人員將無法透過這些方式獲得他們期待的反響。

Andrew Morton 為有抱負的核心開發人員提供了如下建議

::

	所有核心開發者的第一個專案肯定應該是“確保核心在您可以操作的所有
	機器上始終完美執行”。通常的方法是和其他人一起解決問題（這可能需
	要堅持！），但就是如此——這是核心開發的一部分。

(http://lwn.net/Articles/283982/)

在沒有明顯問題需要解決的情況下，通常建議開發人員查看當前的迴歸和開放缺陷
列表。從來都不缺少需要解決的問題；透過解決這些問題，開發人員將從該過程獲得
經驗，同時與開發社群的其他成員建立相互尊重。

