如何快速構建精簡的 Linux 核心¶
本指南介紹如何快速構建 Linux 核心,這些核心非常適合用於測試目的,但對於日常使用來說也完全沒問題。
過程的本質(又名“TL;DR”)¶
[如果您是編譯 Linux 的新手,請忽略此 TLDR 並轉到下面的下一節:它包含一個循序漸進的指南,該指南更詳細,但仍然簡短且易於遵循;該指南及其隨附的參考部分還提到了替代方案、陷阱和其他方面,所有這些都可能與您相關。]
如果您的系統使用 Secure Boot 之類的技術,請準備好允許啟動自行編譯的 Linux 核心;安裝編譯器和構建 Linux 所需的一切;確保您的主目錄中有 12 GB 的可用空間。現在執行以下命令來下載新的 Linux 主線原始碼,然後使用這些原始碼來配置、構建和安裝您自己的核心
git clone --depth 1 -b master \
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git ~/linux/
cd ~/linux/
# Hint: if you want to apply patches, do it at this point. See below for details.
# Hint: it's recommended to tag your build at this point. See below for details.
yes "" | make localmodconfig
# Hint: at this point you might want to adjust the build configuration; you'll
# have to, if you are running Debian. See below for details.
make -j $(nproc --all)
# Note: on many commodity distributions the next command suffices, but on Arch
# Linux, its derivatives, and some others it does not. See below for details.
command -v installkernel && sudo make modules_install install
reboot
如果您以後想構建更新的主線快照,請使用以下命令
cd ~/linux/
git fetch --depth 1 origin
# Note: the next command will discard any changes you did to the code:
git checkout --force --detach origin/master
# Reminder: if you want to (re)apply patches, do it at this point.
# Reminder: you might want to add or modify a build tag at this point.
make olddefconfig
make -j $(nproc --all)
# Reminder: the next command on some distributions does not suffice.
command -v installkernel && sudo make modules_install install
reboot
循序漸進指南¶
原則上,編譯您自己的 Linux 核心很容易。有很多種方法可以做到這一點。哪些方法實際上有效並且是最好的取決於具體情況。
本指南介紹了一種非常適合那些想從原始碼快速安裝 Linux 而不受複雜細節困擾的人的方法;目標是涵蓋在運行於商品 PC 或伺服器硬體上的主流 Linux 發行版上通常需要的一切。
所描述的方法非常適合用於測試目的,例如嘗試建議的修復程式或檢查問題是否已在最新的程式碼庫中修復。儘管如此,以這種方式構建的核心對於日常使用也完全沒問題,同時也很容易保持最新狀態。
以下步驟描述了該過程的重要方面;後面的綜合參考部分更詳細地解釋了其中的每一個步驟。它有時還會描述替代方法、陷阱以及可能在特定點發生的錯誤——以及如何重新開始。
建立一個新的備份,並將系統修復和還原工具放在手邊,以便為發生意外情況做好準備。
[詳情]
在具有“安全啟動”或類似技術的平臺上,準備好一切,以確保系統以後允許您自行編譯的核心啟動。在商品 x86 系統上實現此目的的最快、最簡單的方法是在 BIOS 設定實用程式中停用此類技術;或者,透過
mokutil --disable-validation啟動的過程來刪除其限制。[詳情]
安裝構建 Linux 核心所需的所有軟體。通常您需要:‘bc’、‘binutils’(‘ld’ et al.)、‘bison’、‘flex’、‘gcc’、‘git’、‘openssl’、‘pahole’、‘perl’ 以及 ‘libelf’ 和 ‘openssl’ 的開發標頭檔案。參考部分顯示瞭如何在各種流行的 Linux 發行版上快速安裝這些檔案。
[詳情]
確保有足夠的可用空間來構建和安裝 Linux。對於後者,/lib/ 中 150 兆位元組和 /boot/ 中 100 兆位元組是一個安全的選擇。對於儲存原始碼和構建工件,您的主目錄中通常應該有 12 GB 的空間。如果您的可用空間較少,請務必檢視參考部分中解釋調整核心構建配置的步驟:它提到了一個技巧,可以將 /home/ 中所需的空間減少到大約 4 GB。
[詳情]
檢索您要構建的 Linux 版本的原始碼;然後更改到包含它們的目錄中,因為本指南中的所有其他命令都應從那裡執行。
[注意:以下段落描述瞭如何透過部分克隆 Linux 穩定 git 儲存庫來檢索原始碼。這稱為淺克隆。參考部分解釋了兩種替代方法: 打包的存檔 和 完整的 git 克隆 ;如果下載大量資料不會困擾您,則首選後者,因為它將避免參考部分解釋的淺克隆的一些 特殊特性 。]
首先,執行以下命令來檢索新的主線程式碼庫
git clone --no-checkout --depth 1 -b master \ https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git ~/linux/ cd ~/linux/如果您想訪問最近的主線版本和預釋出版本,請將克隆的歷史記錄加深到您感興趣的最舊的主線版本
git fetch --shallow-exclude=v6.0 origin如果您想訪問穩定/長期版本(例如 v6.1.5),只需新增包含該系列的 branch;之後,至少獲取到啟動該系列的主線版本(v6.1)的歷史記錄
git remote set-branches --add origin linux-6.1.y git fetch --shallow-exclude=v6.0 origin現在檢出您感興趣的程式碼。如果您剛剛執行了初始克隆,您將能夠檢出一個新的主線程式碼庫,這對於檢查開發人員是否已經修復了問題非常理想
git checkout --detach origin/master如果您加深了克隆,則可以指定您加深到的版本(上面的
v6.0)而不是origin/master;後面的版本(如v6.1)和預釋出版本(如v6.2-rc1)也可以正常工作。如果按所述添加了適當的穩定/長期 branch,則穩定或長期版本(如v6.1.5)的工作方式相同。[詳情]
如果您想應用核心補丁,請立即執行。通常這樣的命令可以解決問題
patch -p1 < ../proposed-fix.patch是否實際需要
-p1取決於補丁的建立方式;如果它不適用,請嘗試不使用它。如果您使用 git 克隆了原始碼,並且出現任何問題,請執行
git reset --hard以撤消對原始碼的任何更改。[詳情]
如果您已修補了核心,或者已經安裝了相同版本的核心,最好為要構建的核心新增一個唯一的標籤
echo "-proposed_fix" > localversion稍後在您的核心下執行
uname -r將列印類似 “6.1-rc4-proposed_fix” 的內容。[詳情]
基於現有配置為您的核心建立構建配置。
如果您已經自己準備了這樣的 “.config” 檔案,請將其複製到 ~/linux/ 並執行
make olddefconfig。如果您的發行版或其他人已經根據您或您的硬體的需求定製了您正在執行的核心,請使用相同的命令:然後 make target “olddefconfig” 將嘗試使用該核心的 .config 作為 base。
對於其他人來說,使用此 make target 也可以,但您通常可以透過使用此命令來節省大量時間
yes "" | make localmodconfig這將嘗試選擇您發行版的核心作為 base,然後為您的設定顯然多餘的任何功能停用模組。這將大大減少編譯時間,尤其是當您執行來自商品 Linux 發行版的通用核心時。
有一個問題:“localmodconfig” 可能會停用自您啟動 Linux 以來未使用的核心功能——例如,當前斷開連線的外圍裝置的驅動程式或尚未使用的虛擬化軟體。您可以使用參考部分概述的技巧來減少或幾乎消除這種風險;但是,當構建僅用於快速測試目的的核心時,缺少此類功能通常可以忽略不計。但是,在使用使用此 make target 構建的核心時,您應該牢記這一方面,因為它可能是您偶爾使用的某些功能停止工作的原因。
[詳情]
檢查您是否可能想要或必須調整一些核心配置選項
構建核心的映象和模組
make -j $(nproc --all)如果您希望將核心打包為 deb、rpm 或 tar 檔案,請參閱參考部分中的替代方案。
[詳情]
現在安裝您的核心
command -v installkernel && sudo make modules_install install通常,您之後要做的就是
reboot,因為許多商品 Linux 發行版會在您的引導載入程式的配置中建立一個 initramfs(也稱為 initrd)和核心的條目;但是在某些發行版上,您必須手動執行這兩個步驟,原因參考部分解釋了。在少數發行版(如 Arch Linux 及其衍生產品)上,上面的命令根本不起作用;在這種情況下,您必須手動安裝核心,如參考部分所述。
如果您正在執行不可變的 Linux 發行版,請檢視其文件和網路,以瞭解如何在其中安裝您自己的核心。
[詳情]
稍後要構建另一個核心,您需要類似的步驟,但有時需要略有不同的命令。
首先,切換回原始碼樹
cd ~/linux/如果您想構建來自您尚未使用的穩定/長期系列的某個版本(例如 6.2.y),請告訴 git 跟蹤它
git remote set-branches --add origin linux-6.2.y現在獲取最新的上游更改;您再次需要指定您關心的最早版本,因為 git 否則可能會檢索整個提交歷史
git fetch --shallow-exclude=v6.0 origin現在切換到您感興趣的版本——但請注意,此處使用的命令將丟棄您執行的任何修改,因為它們會與您要檢出的原始碼衝突
git checkout --force --detach origin/master此時,您可能想再次修補原始碼或設定/修改構建標籤,如前所述。之後,使用 olddefconfig 將構建配置調整為新的程式碼庫,這將使用您之前為下一個核心準備的 localmodconfig (~/linux/.config) 調整配置檔案
# reminder: if you want to apply patches, do it at this point # reminder: you might want to update your build tag at this point make olddefconfig現在構建您的核心
make -j $(nproc --all)之後,如上所述安裝核心
command -v installkernel && sudo make modules_install install[詳情]
您的核心稍後很容易刪除,因為它的各個部分僅儲存在兩個位置,並且可以透過核心的版本名稱清楚地識別出來。只需確保不要刪除您正在執行的核心,因為這可能會導致您的系統無法啟動。
首先刪除包含核心模組的目錄,該目錄以其版本名稱命名——在以下示例中為 “6.0.1-foobar”
sudo rm -rf /lib/modules/6.0.1-foobar現在嘗試以下命令,該命令將在某些發行版上刪除所有其他已安裝的核心檔案,同時從引導載入程式配置中刪除核心的條目
command -v kernel-install && sudo kernel-install -v remove 6.0.1-foobar如果該命令沒有任何輸出或失敗,請參閱參考部分;如果 /boot/ 中仍然存在任何名為“6.0.1-foobar”的檔案,請執行相同的操作。
[詳情]
您在遵循上述任何步驟時是否遇到問題,而以下參考部分未清除這些問題?或者您是否有任何想法可以改進文字?然後請花一點時間,並透過電子郵件告知本文件的維護者(Thorsten Leemhuis <linux@leemhuis.info>),理想情況下,同時抄送 Linux 文件郵件列表(linux-doc@vger.kernel.org)。這種反饋對於進一步改進本文件至關重要,這符合每個人的利益,因為它將使更多人能夠掌握此處描述的任務。
循序漸進指南的參考部分¶
本節包含上述指南中每個步驟的附加資訊。
為緊急情況做好準備¶
建立一個新的備份,並將系統修復和還原工具放在手邊 [...]
請記住,您正在處理計算機,計算機有時會做出意想不到的事情——特別是如果您擺弄作業系統的核心等關鍵部件。這就是您將在此過程中要做的事情。因此,最好為發生意外情況做好準備,即使這種情況不應該發生。
[返回循序漸進指南]
處理安全啟動之類的技術¶
在具有“安全啟動”或類似技術的平臺上,準備好一切,以確保系統以後允許您自行編譯的核心啟動。 [...]
許多現代系統只允許某些作業系統啟動;因此,預設情況下,它們將拒絕啟動自行編譯的核心。
理想情況下,您應該透過使您的平臺信任您使用證書和簽名自行構建的核心來解決此問題。此處未介紹如何執行此操作,因為它需要各種步驟,這些步驟會使文字偏離其目的太遠;“核心模組簽名工具”和各種網站已經更詳細地解釋了這一點。
暫時停用安全啟動之類的解決方案是使您自己的 Linux 啟動的另一種方法。在商品 x86 系統上,可以在 BIOS 設定實用程式中執行此操作;此處未介紹執行此操作的步驟,因為它們在機器之間差異很大。
在主流 x86 Linux 發行版上,還有第三種通用選項:停用 Linux 環境的所有安全啟動限制。您可以透過執行 mokutil --disable-validation 來啟動此過程;這將告訴您建立一個一次性密碼,可以安全地將其寫下來。現在重新啟動;在您的 BIOS 執行完所有自檢後,引導載入程式 Shim 將顯示一個藍色框,其中包含訊息“按任意鍵執行 MOK 管理”。在倒計時暴露之前按一些鍵。這將開啟一個選單,並在其中選擇“更改安全啟動狀態”。Shim 的 “MokManager” 現在會要求您輸入之前指定的一次性密碼中的三個隨機選擇的字元。提供這些字元後,確認您確實要停用驗證。之後,允許 MokManager 重新啟動機器。
[返回循序漸進指南]
安裝構建要求¶
安裝構建 Linux 核心所需的所有軟體。 [...]
核心非常獨立,但除了編譯器之類的工具外,您有時還需要一些庫來構建核心。如何安裝所需的一切取決於您的 Linux 發行版和您要構建的核心的配置。
以下是一些在一些主流發行版上通常需要的內容示例
Debian、Ubuntu 及其衍生產品
sudo apt install bc binutils bison dwarves flex gcc git make openssl \ pahole perl-base libssl-dev libelf-devFedora 及其衍生產品
sudo dnf install binutils /usr/include/{libelf.h,openssl/pkcs7.h} \ /usr/bin/{bc,bison,flex,gcc,git,openssl,make,perl,pahole}openSUSE 及其衍生產品
sudo zypper install bc binutils bison dwarves flex gcc git make perl-base \ openssl openssl-devel libelf-dev
如果您想知道為什麼這些列表包含 openssl 及其開發標頭檔案:它們是安全啟動支援所必需的,許多發行版在其 x86 機器的核心配置中啟用了安全啟動支援。
有時您還需要用於壓縮格式(如 bzip2、gzip、lz4、lzma、lzo、xz 或 zstd)的工具。
如果您執行本指南中未涵蓋的任務,則可能需要其他庫及其開發標頭檔案。例如,當從 tools/ 目錄構建核心工具時,將需要 zlib;使用 “menuconfig” 或 “xconfig” 之類的 make target 調整構建配置將需要 ncurses 或 Qt5 的開發標頭檔案。
[返回循序漸進指南]
空間要求¶
確保有足夠的可用空間來構建和安裝 Linux。 [...]
提到的數字是粗略的估計值,並且有很大的額外費用,以確保安全,因此通常您需要的空間會更少。
如果您的空間有限,請記住在您到達 關於配置調整的部分 時閱讀參考部分,因為確保停用除錯符號將減少相當數量的千兆位元組的已用磁碟空間。
[返回循序漸進指南]
下載原始碼¶
檢索您要構建的 Linux 版本的原始碼。 [...]
循序漸進指南概述瞭如何使用淺 git 克隆來檢索 Linux 的原始碼。關於此方法還有 更多要說的,還有兩種值得描述的替代方法:打包的存檔 和 完整的 git 克隆。以及方面“使用適當的預釋出版本而不是最新的主線程式碼是否更明智”和“如何獲得更新的主線程式碼庫”也需要詳細說明。
請注意,為了使事情簡單,本指南中使用的命令將構建工件儲存在原始碼樹中。如果您希望分離它們,只需將類似 O=~/linux-builddir/ 的內容新增到所有 make 呼叫中;還要調整所有新增檔案或修改任何生成的(例如您的 “.config”)檔案的命令中的路徑。
[返回循序漸進指南]
淺克隆的值得注意的特性¶
循序漸進指南使用淺克隆,因為它是本文件大多數目標受眾的最佳解決方案。這種方法有幾個值得一提的方面
本文件在大多數地方使用帶有
--shallow-exclude=的git fetch來指定您關心的最早版本(或者更準確地說:它的 git 標籤)。您也可以使用引數--shallow-since=來指定絕對日期(例如'2023-07-15')或相對日期('12 months')來定義您要下載的歷史記錄的深度。作為第二種替代方法,您還可以使用類似--depth=1的引數顯式指定某個深度,除非您為穩定/長期核心新增 branch。執行
git fetch時,請記住始終指定您關心的最舊版本、時間或顯式深度,如循序漸進指南所示。否則,您將冒著下載幾乎整個 git 歷史記錄的風險,這將消耗相當多的時間和頻寬,同時也會給伺服器帶來壓力。請注意,您不必一直使用相同的版本或日期。但是,當您隨著時間的推移更改它時,git 會將歷史記錄加深或展平到指定的點。這使您可以檢索最初認為不需要的版本——或者它將丟棄舊版本的原始碼,例如在您想釋放一些磁碟空間的情況下。當使用
--shallow-since=或--depth=時,後者將自動發生。請注意,在加深克隆時,您可能會遇到類似 “fatal: error in object: unshallow cafecaca0c0dacafecaca0c0dacafecaca0c0da” 的錯誤。在這種情況下,執行
git repack -d並重試``如果您想從某個版本(例如 Linux 6.3)恢復更改或執行二分查詢 (v6.2..v6.3),最好告訴
git fetch檢索最多三個版本之前的物件(例如 6.0):git describe之後將能夠像在完整的 git 克隆中一樣描述大多數提交。
使用軟體包存檔下載原始碼¶
編譯 Linux 的新手通常認為透過 https://kernel.linux.club.tw 的 front-page 下載存檔是檢索 Linux 原始碼的最佳方法。如果您確定只構建一個特定的核心版本而不更改任何程式碼,那麼這實際上是可以的。問題是:您可能確信情況會是這樣,但實際上它通常會被證明是錯誤的假設。
這是因為在報告或除錯問題時,開發人員通常會要求嘗試另一個版本。他們也可能會建議使用 git revert 暫時撤消提交,或者可能會提供各種補丁來嘗試。有時還會要求報告者使用 git bisect 來查詢導致問題的更改。這些事情依賴於 git,或者使用 git 處理起來更容易、更快捷。
淺克隆也不會增加任何顯著的開銷。例如,當您使用 git clone --depth=1 建立最新的主線程式碼庫的淺克隆時,git 只會檢索比透過 kernel.org 的 front-page 下載最新的主線預釋出版本(又名“rc”)略多的資料。
因此,淺克隆通常是更好的選擇。如果您仍然想使用打包的原始碼存檔,請透過 kernel.org 下載一個存檔;之後,將其內容提取到某個目錄,然後更改為提取過程中建立的子目錄。除了依賴 git 的內容外,循序漸進指南的其餘部分都可以正常工作——但這主要涉及關於其他版本的連續構建的部分。
使用完整的 git 克隆下載原始碼¶
如果下載和儲存大量資料(截至 2023 年初,約為 4.4 千兆位元組)不會困擾您,請執行完整的 git 克隆而不是淺克隆。然後,您將避免上面提到的特殊性,並且可以隨時掌握所有版本和單個提交
curl -L \
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/clone.bundle \
-o linux-stable.git.bundle
git clone linux-stable.git.bundle ~/linux/
rm linux-stable.git.bundle
cd ~/linux/
git remote set-url origin \
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
git fetch origin
git checkout --detach origin/master
適當的預釋出版本 (RC) 與最新的主線版本¶
當使用 git 克隆原始碼並檢出 origin/master 時,您通常會檢索到一個程式碼庫,該程式碼庫介於最新版本和下一個版本或預釋出版本之間。這幾乎總是您想嘗試主線程式碼時想要的程式碼:v6.1-rc5 之類的預釋出版本沒有任何特殊之處,因為它們在釋出之前不會進行任何重要的額外測試。
有一個例外:你可能希望堅持最新的主線版本(例如 v6.1),直到其後續版本的第一個預釋出版(v6.2-rc1)釋出。這是因為在此期間,編譯器錯誤和其他問題更有可能發生,因為主線此時處於“合併視窗”:通常為期兩週的階段,其中下一個版本的大部分更改都會被合併。
避免主線延遲¶
淺克隆和完整克隆的解釋都從 Linux 穩定版 git 倉庫檢索程式碼。這使得本文件的讀者更容易理解,因為它允許輕鬆訪問主線和穩定/長期維護版本。這種方法只有一個缺點
合併到主線倉庫的更改每隔幾個小時才會同步到 Linux 穩定版倉庫的 master 分支。這種延遲通常不必擔心;但是,如果您真的需要最新的程式碼,只需將主線倉庫新增為額外的遠端倉庫,然後從那裡檢出程式碼
git remote add mainline \
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
git fetch mainline
git checkout --detach mainline/master
在使用淺克隆執行此操作時,請記住使用前面描述的引數之一呼叫 git fetch 以限制深度。
修補原始碼(可選)¶
如果您想應用核心補丁,請立即執行。 [...]
這是您可能需要修補核心的時候——例如,當開發人員提出了一個修復程式並要求您檢查它是否有幫助時。逐步指南已經解釋了這裡的所有關鍵內容。
[返回逐步指南]
標記此核心構建(可選,通常是明智的)¶
如果您修補了核心或已經安裝了該核心版本,最好透過擴充套件其釋出名稱來標記您的核心: [...]
標記核心將有助於避免以後出現混淆,尤其是在您修補了核心的情況下。新增單獨的標籤還將確保核心映像及其模組與任何現有核心並行安裝。
有多種方法可以新增這樣的標籤。逐步指南透過在構建目錄中建立一個“localversion”檔案來實現這一點,核心構建指令碼將自動從中拾取標籤。您可以稍後更改該檔案以在後續構建中使用不同的標籤,或者直接刪除該檔案以轉儲標籤。
[返回逐步指南]
定義核心的構建配置¶
基於現有配置為核心建立構建配置。 [...]
此步驟的各個方面需要更仔細的解釋
使用另一個配置檔案作為基礎時的陷阱¶
像 localmodconfig 和 olddefconfig 這樣的 make 目標有一些你想要注意的常見陷阱
這些目標將重用構建目錄中的核心構建配置(例如“~/linux/.config”),如果存在的話。如果您想從頭開始,則需要刪除它。
make 目標會嘗試自動查詢正在執行的核心的配置,但可能選擇不佳。像 '# using defaults found in /boot/config-6.0.7-250.fc36.x86_64' 或 'using config: ‘/boot/config-6.0.7-250.fc36.x86_64’' 這樣的行會告訴你它們選擇了哪個檔案。如果這不是預期的檔案,只需在使用這些 make 目標之前將其儲存為“~/linux/.config”。
如果您嘗試在舊版本(例如 v5.15)上使用為某個核心(例如 v6.0)準備的配置檔案,則可能會發生意想不到的事情。在這種情況下,您可能需要使用一個配置作為基礎,該配置是您的發行版在使用該核心或稍微舊的核心版本時使用的。
影響配置¶
make 目標 olddefconfig 和使用 localmodconfig 時使用的 yes "" | 會將任何未定義的構建選項設定為其預設值。這尤其會停用在您的基本核心釋出後引入的許多核心功能。
如果您想手動設定這些配置選項,請使用 oldconfig 而不是 olddefconfig,或者在使用 localmodconfig 時省略 yes "" |。然後,對於每個未定義的配置選項,您都會被問到如何進行。如果您不確定如何回答,只需按“Enter”鍵即可應用預設值。
使用 localmodconfig 時的大陷阱¶
正如逐步指南中已經簡要解釋的那樣:使用 localmodconfig 很容易發生您自己構建的核心會缺少您在使用此 make 目標之前未執行的任務的模組。 這是因為這些任務需要核心模組,這些模組通常在您第一次執行該任務時會自動載入; 如果您在使用 localmodconfig 之前至少沒有執行過該任務一次,則後者會認為這些模組是多餘的並停用它們。
您可以嘗試透過執行通常會自動載入其他核心模組的典型任務來避免這種情況:啟動 VM,建立 VPN 連線,迴圈掛載 CD/DVD ISO,掛載網路共享(CIFS、NFS、...),並連線所有外部裝置(2FA 金鑰、耳機、網路攝像頭、...)以及具有您通常不使用的檔案系統的儲存裝置(btrfs、ext4、FAT、NTFS、XFS、...)。 但很難想到可能需要的一切 - 即使核心開發人員也經常在此處忘記一件事或另一件事。
不要讓這種風險困擾您,尤其是在僅出於測試目的編譯核心時:通常至關重要的一切都會存在。 如果您忘記了重要的內容,您可以稍後開啟缺少的功能,並快速執行命令來編譯和安裝更好的核心。
但是,如果您計劃定期構建和使用自己構建的核心,您可能希望透過記錄系統在幾周內載入的模組來降低風險。您可以使用 modprobed-db 自動化此過程。 之後,使用 LSMOD=<path> 將 localmodconfig 指向 modprobed-db 注意到的正在使用的模組列表
yes "" | make LSMOD="${HOME}"/.config/modprobed.db localmodconfig
使用 localmodconfig 進行遠端構建¶
如果您想使用 localmodconfig 為另一臺機器構建核心,請在其上執行 lsmod > lsmod_foo-machine,並將該檔案傳輸到您的構建主機。 現在將構建指令碼指向該檔案,如下所示:yes "" | make LSMOD=~/lsmod_foo-machine localmodconfig。 請注意,在這種情況下,您可能也想從另一臺機器複製一個基本的核心配置,並將其作為 .config 放置在您的構建目錄中。
[返回逐步指南]
調整構建配置¶
檢查您是否可能想要或必須調整一些核心配置選項
根據您的需要,此時您可能想要或必須調整一些核心配置選項。
除錯符號¶
評估您希望如何處理除錯符號。 [...]
大多數使用者不需要關心這個問題,通常可以保持原樣;但是如果您可能需要解碼堆疊跟蹤或想要減少空間消耗,則應該仔細檢視此內容。
當核心在執行時丟擲“panic”、“Oops”、“warning”或“BUG”時,擁有可用的除錯符號可能很重要,因為這樣您就可以找到程式碼中發生問題的確切位置。 但是,收集和嵌入所需的除錯資訊需要時間並消耗相當多的空間:在 2022 年末,配置為 localmodconfig 的典型 x86 核心的構建工件在使用除錯符號時消耗了大約 5 GB 的空間,但在停用它們時消耗的空間不到 1 GB。 生成的核心映像和模組也更大,這會增加載入時間。
因此,如果您想要一個小的核心並且不太可能以後解碼堆疊跟蹤,您可能需要停用除錯符號以避免上述缺點
./scripts/config --file .config -d DEBUG_INFO \
-d DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT -d DEBUG_INFO_DWARF4 \
-d DEBUG_INFO_DWARF5 -e CONFIG_DEBUG_INFO_NONE
make olddefconfig
另一方面,如果很有可能以後需要解碼堆疊跟蹤(如 受汙染的核心 中的“解碼失敗訊息”更詳細地解釋的那樣),那麼您肯定希望啟用它們
./scripts/config --file .config -d DEBUG_INFO_NONE -e DEBUG_KERNEL
-e DEBUG_INFO -e DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT -e KALLSYMS -e KALLSYMS_ALL
make olddefconfig
請注意,許多主流發行版在其核心配置中啟用了除錯符號 - 因此像 localmodconfig 和 olddefconfig 這樣的 make 目標通常會拾取該設定。
[返回逐步指南]
特定於發行版的調整¶
您正在執行 [...]
以下部分幫助您避免在一些常用發行版上遵循本指南時已知會發生的構建問題。
Debian
刪除對證書檔案的過時引用,該引用會導致您的構建失敗
./scripts/config --file .config --set-str SYSTEM_TRUSTED_KEYS ''或者,下載所需的證書並使該配置選項指向它,如 Debian 手冊更詳細地解釋的那樣 - 或者生成您自己的證書,如 核心模組簽名工具 中解釋的那樣。
[返回逐步指南]
個別調整¶
如果您想影響配置的其他方面,請立即執行 [...]
此時您可以使用像 make menuconfig 這樣的命令來使用基於文字的使用者介面啟用或停用某些功能; 要使用圖形配置實用程式,請改用 make 目標 xconfig 或 gconfig。 所有這些都需要基於的工具包(ncurses、Qt5、Gtk2)的開發庫; 如果缺少某些必需的庫,則會顯示一條錯誤訊息。
[返回逐步指南]
構建你的核心¶
構建核心的映像和模組 [...]
在此階段可能會發生很多錯誤,但以下說明將幫助您自助。 另一個小節解釋瞭如何將核心直接打包為 deb、rpm 或 tar 檔案。
處理構建錯誤¶
當發生構建錯誤時,可能是由您機器設定的某些方面引起的,這些方面通常可以快速修復; 但是,其他時候,問題在於程式碼中,只能由開發人員修復。 仔細檢查失敗訊息並結合在網際網路上進行一些研究通常會告訴您是哪一種。 要執行這樣的調查,請像這樣重新啟動構建過程
make V=1
V=1 啟用詳細輸出,這可能需要檢視實際錯誤。 為了更容易發現,此命令還省略了 -j $(nproc --all) 以前使用的命令,以利用系統中用於該作業的每個 CPU 核心 - 但當發生故障時,這種並行性也會導致一些混亂。
幾秒鐘後,構建過程應再次遇到錯誤。 現在嘗試找到描述問題的最關鍵的一行。 然後在網際網路上搜索該行中最重要和非通用的部分(例如 4 到 8 個字); 避免或刪除任何看起來與系統相關的東西,例如您的使用者名稱或像 /home/username/linux/ 這樣的本地路徑名。 首先使用該字串透過常規網際網路搜尋引擎進行搜尋,然後透過 lore.kernel.org/all/ 搜尋 Linux 核心郵件列表。
大多數情況下,這將找到一些可以解釋錯誤原因的內容; 很多時候,其中一個點選也會為您的問題提供解決方案。 如果您沒有找到任何與您的問題匹配的內容,請透過修改搜尋詞或使用錯誤訊息中的另一行,從不同的角度再次嘗試。
最後,您遇到的絕大多數問題可能已經被其他人遇到並報告過了。 這包括原因不是您的系統,而是程式碼的問題。 如果您遇到其中一種情況,您也可能會找到針對您的問題的解決方案(例如補丁)或解決方法。
打包你的核心¶
逐步指南使用預設的 make 目標(例如 x86 上的“bzImage”和“modules”)來構建核心的映像和模組,該指南的後續步驟會安裝這些映像和模組。 您也可以使用以下目標直接構建所有內容並直接打包:
make -j $(nproc --all) bindeb-pkg生成 deb 包
make -j $(nproc --all) binrpm-pkg生成 rpm 包
make -j $(nproc --all) tarbz2-pkg生成 bz2 壓縮 tarball
這只是用於此目的的可用 make 目標的選擇,請參閱 make help 以瞭解其他目標。 您也可以在執行 make -j $(nproc --all) 後使用這些目標,因為它們會拾取已構建的所有內容。
如果您使用目標來生成 deb 或 rpm 包,請忽略逐步指南中有關安裝和刪除核心的說明; 而是使用格式的包實用程式(例如 dpkg 和 rpm)或構建在其上的包管理實用程式(apt、aptitude、dnf/yum、zypper、...)來安裝和刪除包。 請注意,使用這兩個 make 目標生成的包旨在在利用這些格式的各種發行版上工作,因此它們的行為有時會與發行版的核心包不同。
[返回逐步指南]
安裝你的核心¶
現在安裝你的核心 [...]
在逐步指南中執行命令後需要執行的操作取決於 installkernel 可執行檔案是否存在及其實現。 許多常用的 Linux 發行版在 /sbin/ 中提供了一個這樣的核心安裝程式,它可以完成所需的一切,因此除了重新啟動之外,您無需執行任何操作。 但是,某些發行版包含僅完成部分作業的 installkernel - 還有一些完全缺少它,並將所有工作都留給您。
如果找到 installkernel,核心的構建系統會將核心映像和相關檔案的實際安裝委託給此可執行檔案。 在幾乎所有 Linux 發行版上,它會將映像儲存為“/boot/vmlinuz-
許多發行版上的 Installkernel 之後會生成一個“initramfs”(通常也稱為“initrd”),常用發行版依賴它進行引導; 因此,請務必保持逐步指南中使用的兩個 make 目標的順序,因為如果在核心的模組之前安裝其映像,事情會出錯。 通常,installkernel 也會將您的核心新增到引導載入程式配置中。 如果您的發行版的 installkernel 不處理它們,您必須自己處理這些任務中的一項或兩項。
像 Arch Linux 及其衍生產品一樣,一些發行版完全缺少 installkernel 可執行檔案。 在這些發行版上,只需使用核心的構建系統安裝模組,然後手動安裝映像和 System.map 檔案
sudo make modules_install
sudo install -m 0600 $(make -s image_name) /boot/vmlinuz-$(make -s kernelrelease)
sudo install -m 0600 System.map /boot/System.map-$(make -s kernelrelease)
如果您的發行版在 initramfs 的幫助下啟動,請現在使用您的發行版為此過程提供的工具為您的核心生成一個。 之後,將您的核心新增到引導載入程式配置並重新啟動。
[返回逐步指南]
稍後進行另一輪¶
要稍後構建另一個核心,您需要類似但有時略有不同的命令 [...]
構建稍後核心的過程類似,但在某些方面略有不同。 例如,您不希望為後續核心構建使用“localmodconfig”,因為您已經建立了一個精簡的配置,您希望從現在開始使用該配置。 因此,只需使用 oldconfig 或 olddefconfig 來根據您即將構建的核心版本的需要調整您的構建配置。
如果您使用 git 建立了淺克隆,請記住詳細解釋設定的部分:您需要使用略有不同的 git fetch 命令,並且在切換到另一個系列時需要新增一個額外的遠端分支。
[返回逐步指南]
稍後解除安裝核心¶
已安裝核心的所有部分都可以透過其釋出名稱識別,因此以後很容易刪除。 [...]
不要擔心手動安裝核心並因此繞過發行版的打包系統會完全搞亂您的機器:核心的所有部分都很容易在以後刪除,因為檔案僅儲存在兩個位置,並且通常可以透過核心的釋出名稱識別。
其中一個位置是 /lib/modules/ 中的目錄,其中包含每個已安裝核心的模組。 此目錄以核心的釋出名稱命名; 因此,要刪除某個核心的所有模組,只需刪除 /lib/modules/ 中的模組目錄即可。
另一個位置是 /boot/,在核心安裝期間通常會在其中放置一到五個檔案。 所有這些檔案通常都在其檔名中包含釋出名稱,但是有多少檔案及其名稱在某種程度上取決於發行版的 installkernel 可執行檔案(見上文)及其 initramfs 生成器。 在某些發行版上,逐步指南中提到的 kernel-install 命令會為您刪除所有這些檔案 - 同時也會刪除引導載入程式配置中您的核心的條目。 在其他發行版上,您必須自己處理這些步驟。 以下命令應以互動方式刪除釋出名稱為“6.0.1-foobar”的核心的兩個主要檔案
rm -i /boot/{System.map,vmlinuz}-6.0.1-foobar
現在刪除所屬的 initramfs,它通常被稱為類似 /boot/initramfs-6.0.1-foobar.img 或 /boot/initrd.img-6.0.1-foobar。 之後,檢查 /boot/ 中是否有名稱中包含“6.0.1-foobar”的其他檔案,並將它們也刪除。 現在從引導載入程式的配置中刪除核心。
請注意,在手動刪除核心的檔案或目錄時,要非常小心使用像“*”這樣的萬用字元:當您只想刪除 6.0 或 6.0.1 時,可能會意外刪除 6.0.11 核心的檔案。
[返回逐步指南]
常見問題解答¶
為什麼這個“操作指南”在我的系統上不起作用?¶
正如最初宣告的那樣,本指南“旨在涵蓋在執行在常用 PC 或伺服器硬體上的主流 Linux 發行版上[構建核心]通常需要的所有內容”。 儘管如此,概述的方法也應該在許多其他設定上有效。 但是,嘗試在一個指南中涵蓋每種可能的用例都會適得其反,因為如果沒有這樣的重點,您將需要沿著“如果您有 <插入機器或發行版>,您此時必須執行 <此和彼> <代替|另外>”的思路構建數十或數百個構造。 每一種都會使文字更長、更復雜且更難遵循。
話雖如此:這當然是一種平衡行為。 因此,如果您認為其他用例值得描述,請將其建議給本文件的維護者,如上文所述。