為什麼要了解核心編譯#

大多數情況下,你不需要自行編譯核心——發行版提供的核心已經夠用了。但理解核心編譯的流程,能幫助你理解 Linux 核心的架構,以及核心與模組之間的關係。

需要自行編譯核心的場景:

  • 特殊硬體支援:發行版核心不包含你需要的驅動程式
  • 效能最佳化:移除不需要的功能,精簡核心以提升效能
  • 新功能需求:需要較新版核心才有的功能
  • 安全性要求:套用特定的安全補丁

核心的組成#

Linux 核心由兩部分組成:

  • 核心主體(vmlinuz):核心的主要程式碼,必須在開機時載入
  • 核心模組(Module):可在運行時動態載入的功能擴充

核心設計的關鍵決策是:哪些功能編譯進核心主體,哪些做成模組。編譯進主體的功能永遠可用但增加核心大小,做成模組的功能按需載入但需要額外的管理。

編譯前的準備#

確認硬體環境#

編譯核心前,需要清楚主機的硬體配置,才能正確選擇要支援的驅動程式和功能。

取得核心原始碼#

從 kernel.org 或發行版的 SRPM 取得原始碼。

清理環境#

  • make mrproper:清除所有編譯產生的檔案和設定,回到乾淨狀態
  • make clean:只清除編譯產生的目的檔,保留設定

核心功能選擇#

核心的功能配置是編譯中最關鍵的步驟。每個功能有三種狀態:

  • [*]<*>:編譯進核心主體
  • <M>:編譯為模組
  • [ ]< >:不編譯

設定工具#

  • make menuconfig:基於文字的選單介面(最常用)
  • make oldconfig:基於現有設定檔,只詢問新增的選項
  • make xconfig:圖形介面(需要 Qt)

如果不確定某個選項的作用,最安全的做法是參考發行版目前核心的設定(/boot/config-$(uname -r))作為起點,在此基礎上進行微調。

編譯與安裝#

編譯步驟#

  1. 編譯核心make bzImage(產生壓縮的核心映像檔)
  2. 編譯模組make modules
  3. 安裝模組make modules_install(安裝到 /lib/modules/核心版本/
  4. 安裝核心:將核心映像檔複製到 /boot/,更新 GRUB2 設定

建立 initramfs#

新核心安裝後,需要建立對應的 initramfs

  • dracut(CentOS 7)或 mkinitramfs 產生 initramfs 映像檔
  • initramfs 必須包含掛載根檔案系統所需的模組

更新 Boot Loader#

執行 grub2-mkconfig 重新產生 GRUB2 設定檔,讓新核心出現在開機選單中。

安裝新核心時,不要移除舊核心。如果新核心有問題無法開機,你還可以從 GRUB2 選單選擇舊核心啟動。至少保留一個已知可正常運作的核心作為退路。

單一模組編譯#

有時候你不需要編譯整個核心,只需要為現有核心編譯一個額外的模組(通常是硬體驅動程式)。這比完整的核心編譯簡單得多:

  1. 取得模組的原始碼
  2. 確認目前核心的 header 檔案已安裝(kernel-devel 套件)
  3. 編譯模組(通常 make 就可以)
  4. 安裝到 /lib/modules/核心版本/
  5. 執行 depmod 更新模組相依性資料庫
  6. modprobe 載入模組

這是在 Linux 上安裝第三方硬體驅動程式(如 NVIDIA 顯示卡驅動、特殊網卡驅動)的常見方式。DKMS(Dynamic Kernel Module Support)可以在核心更新時自動重新編譯這些第三方模組。

核心編譯的實務觀念#

在現代的 Linux 使用中,自行編譯核心的情境已經大幅減少。但這些知識的價值在於:

  • 理解核心與模組的關係,有助於排除驅動程式問題
  • 理解核心設定,有助於效能調校
  • 理解編譯流程,有助於理解 Linux 發行版是如何建構的
  • 在嵌入式系統開發中,客製化核心仍然是必備技能