兩個月新增 80 萬行代碼,Linux 內核維護爲何不會崩?

8 月初,當 Linux 5.8 RC 版本開放測試時,大多數的新聞都聚焦於它的大小,稱其爲「史上最大的內核版本」。正如 Linus Torvalds 本人指出的那樣,「儘管沒有任何一件事情能脫穎而出……但 5.8 彷佛是咱們有史以來最大的發行版之一。」linux

  

確實,剛剛發佈的 Linux 內核 5.8 RC 具備超過 14,000 個 commit,約 80 萬行新代碼以及大約 100 名新貢獻者。要知道,距離 5.7 正式版發佈才僅僅過去了約 2 個月的時間。Linux 內核維護者 Steven Rostedt 認爲,5.8 之因此變得如此之大,頗有多是由於 COVID-19 疫情讓不少人難以出門旅行,全部人都所以可以在這期間完成比平時更多的工做。 git

Rostedt 表示,從一個經驗豐富的 Linux 內核貢獻者和維護者的角度來看,5.8 RC 發行版特別使人震驚的並非它的大小,而是它的空前規模對於那些正在維護它的人來講卻沒有形成困擾,「我認爲這是由於 Linux 具備比世界上任何軟件項目都好的工做流程。」分佈式

擁有最佳的工做流程意味着什麼?對 Rostedt 而言,這歸結爲 Linux 內核開發人員隨着時間的推移創建的一系列基本規則,以使他們可以持續不斷地大規模、可靠地發展 Linux 內核項目。Rostedt 站在一個 Linux 內核資深維護者的角度,爲咱們分享了龐大的 Linux 內核項目 30 年來是如何有條不紊地運轉的。函數

第一個關鍵因素是 Git

首先讓咱們從 Linux 項目的歷史來看。在該項目的早期(1991-2002年),人們只能直接將補丁發送給 Linus Torvalds。準確地說,Linus 從項目的子維護者那裏獲取補丁,而這些子維護者從其餘代碼貢獻者那裏獲取補丁。隨着 Linux 內核變得愈來愈大,代碼愈來愈複雜,很快他們就發現,一切都變得很難擴展和跟蹤,而且項目將始終面臨合併不兼容代碼的風險。工具

 

這致使 Linus 開始探索包括 BitKeeper 在內的各類版本管理工具。BitKeeper 是一種最先的分佈式版本管理的方法,其餘的版本管理系統一般使用簽出/修改/簽入協議,而 BitKeeper 則向全部人提供整個倉庫的副本,並容許開發人員將其變動發送出去以進行合併。Linux 在 2002 年開始短暫地採用了 BitKeeper,可是因爲其自己是一個專有軟件,被認爲不符合社區對開源工做的信念,因而該工具在 2005 年中止使用。爲了尋找替代品,Linus 消失了一段時間,並帶着 git 回來了,後者成爲了更強大的分佈式版本管理系統,而且是管理流程的第一個重要實例化。Git 的出現使 Linux 開發在今天依然運轉良好。性能

Rostedt 爲咱們列出了 Linux 內核工做流程中,圍繞 Git 展開的七個重要基本原則。測試

七大基本原則

每次commit只能作一件事

Linux 的中心原則是,全部更改都必須分解爲小步驟進行 —— 您的每一個commit都只能作一件事。這並不意味着每一個 commit 都必須很小,好比對在數千個文件中使用的函數的API進行簡單更改,可使更改量很大,但仍然能夠接受,由於它是針對某一項單一任務的更改。經過始終遵循此原則,項目維護者能夠更輕鬆地識別和隔離任何有問題的更改,而不影響其餘的功能。spa

commit 不能破壞構建

不只應該將全部更改分解爲儘量小的變量,並且還不能破壞內核。即每一個步驟都必須徹底起做用,而且不引發退化。這就是爲何對函數原型的更改還必須更新調用它的每一個文件,以防止構建中斷的緣由。所以,每一個步驟都必須做爲一個獨立的更改來工做,這將咱們帶到了下一點:日誌

全部代碼都是二等分的

若是在某個時候發現了錯誤,則須要知道是哪一個更改致使了問題。從本質上講,二等分是一種操做,它使開發者能夠找到全部發生錯誤的確切時間點。blog

爲此,請轉到最後一個已知的工做 commit 所在的節點,而且已知第一個 commit 已損壞,而後在該點測試代碼。若是可行,則前進到下一個節點;若是不是,則返回更上層的節點。這樣一來,開發者就能夠在十幾回編譯/測試中,從成千上萬的可能 commit 中分離出致使問題出現的 commit 。Git 甚至能夠經過 git bisect 功能幫助自動化該過程。  

重要的是,這隻有在開發者遵照之前的規則的狀況下才能很好地起做用:每一個 commit 僅作一件事。不然,您將不知道是 commit 的許多更改中的哪個致使了問題;若是 commit 破壞了構建讓整個項目沒法正常啓動,同時等分線又剛好落在了該 commit 上,則您將不知道接下來是該往上一個節點測試仍是往下一個節點測試,由於它們都有問題。這意味着您永遠都不該編寫依賴於未來 commit 的 commit ,例如:調用尚不存在的函數,或更改全局函數的參數而不更改同一 commit 中的全部調用者。

永遠不要 rebase 公共分支

Linux 項目工做流程不容許 rebase 他人使用的任何公共分支。由於 rebase 這些公共分支後,已從新基準化的 commit 將再也不與基於原存儲庫中的相同 commit 匹配。在樹的層次結構中,不是葉子的公共主幹部分不能從新設置基準,不然將會破壞層次結構中的下游分支。

Git 正確合併

其餘的版本管理系統是合併來自不一樣分支代碼的噩夢,它們一般難以弄清代碼衝突,而且須要大量的手動工做來解決。而 Git 的結構能夠輕鬆完成這項工做,所以 Linux 項目也從中直接受益。這就是爲何 5.8 版本的大小並不重要的重要緣由。在 5.8-RC1 發佈週期中,平均天天有 200個 commit ,並從 5.7 版本中繼承了 880 個合併。一些維護者注意到了其中增長的工做量,可是對此仍然沒有感到什麼太大的壓力或者致使倦怠。

保留定義明確的 commit 日誌

不幸的是,這多是許多其餘項目忽略的最重要的原則之一。每一個 commit 都必須是獨立的,這也應該包括與該 commit 相應的日誌。內核貢獻者必須在更改的 commit 日誌中作出說明,讓全部人瞭解與正在進行的更改相關的全部內容。Rostedt 提到,他本身的一些最冗長和最具描述性的變動日誌,每每是針對一些單行代碼提交的,由於這些單行代碼更改是很是細微的錯誤修復,且代碼自己包含的信息極少。所以更改的代碼越少,日誌反而應該說明得更詳細。

在一個 commit 過了幾年以後,幾乎沒有人會記得當初爲何進行更改。Git 的 blame 功能就能夠顯示這些代碼的修改記錄。好比一些 commit 可能很是古老,也許您須要去除一個鎖定,或者對某些代碼進行更改,而又不確切知道它爲何存在,就可使用 git blame 來查看。編寫良好的代碼更改日誌能夠幫助肯定是否能夠刪除該代碼或如何對其進行修改。Rostedt 說:「有好幾回我很高興能在代碼上看到詳細的變動日誌,由於我不得不刪除這些代碼,而變動日誌的描述讓我知道我這麼作是能夠的。」 

持續測試和集成

最後一項基本原則是開發過程當中進行持續測試和持續集成。在向上遊發送 commit 請求以前,開發者會測試每一個 commit 。Linux 社區還有一個名爲 Linux-next 的鏡像 ,它提取維護人員在其存儲庫的特定分支上進行的全部更改,並對其進行測試以確保它們能正確集成。Linux-next 很是有效地運行着整個內核的可測試分支,該分支將用於下一個發行版。Linux-next 是一個公共倉庫,任何人均可以測試它,這種狀況常常發生 —— 人們如今甚至發佈有關 Linux-next 中代碼的錯誤報告。事實上,已經進入 Linux-next 幾周的代碼基本上能夠肯定會最終進入主線發行版中。

軟件開發行業的黃金標準

全部的這些原則制度使 Linux 社區可以以如此龐大的規模(常規 9 周爲一個版本迭代週期)發佈使人難以置信的可靠代碼(每一個版本平均 10,000 次 commit ,最後一個版本超過 14,000 次 commit )。   

Rostedt 指出,Linux 項目取得空前成功的另外一個因素是他們社區的文化。Linux 內核社區內部存在一種持續改進的文化,這使他們可以首先採用這些實踐。同時他們還有一種信任的文化,「咱們有一條清晰的途徑,人們能夠經過該途徑作出貢獻,並隨着時間的推移證實他們願意且有能力推動該項目的發展。這將創建一個相互信任的關係網,這些關係對於項目的長期成功相當重要。」

Rostedt 認爲,內核開發者的肩上承擔着比其餘任何項目都要重的責任。「在內核層,咱們別無選擇,只能遵循這些作法。由於全部其餘應用程序都在內核之上運行,內核中的任何性能問題或錯誤都將致使上層的應用程序出現性能問題或錯誤。咱們必須完美處理內核中的錯誤,不然,整個計算機系統都將受到損害。咱們很是關心每一個錯誤,由於內核中的錯誤帶來的風險很高,這種思惟方式也能讓咱們很好地服務於任何軟件項目。」 

上層的應用程序會由於錯誤而崩潰,形成的後果多是惹惱用戶,但風險不高。而內核的錯誤可能致使的後果是讓計算機上的一切都出現問題,承擔着巨大的風險。

這就是 Linux 內核開發工做流程被視爲軟件開發行業黃金標準的緣由。

 

原文連接:點擊查看

相關文章
相關標籤/搜索