為什麼要了解核心編譯#
大多數情況下,你不需要自行編譯核心——發行版提供的核心已經夠用了。但理解核心編譯的流程,能幫助你理解 Linux 核心的架構,以及核心與模組之間的關係。
需要自行編譯核心的場景:
- 特殊硬體支援:發行版核心不包含你需要的驅動程式
- 效能最佳化:移除不需要的功能,精簡核心以提升效能
- 新功能需求:需要較新版核心才有的功能
- 安全性要求:套用特定的安全補丁
核心的組成#
Linux 核心由兩部分組成:
- 核心主體(vmlinuz):核心的主要程式碼,必須在開機時載入
- 核心模組(Module):可在運行時動態載入的功能擴充
核心設計的關鍵決策是:哪些功能編譯進核心主體,哪些做成模組。編譯進主體的功能永遠可用但增加核心大小,做成模組的功能按需載入但需要額外的管理。
編譯前的準備#
確認硬體環境#
編譯核心前,需要清楚主機的硬體配置,才能正確選擇要支援的驅動程式和功能。
取得核心原始碼#
從 kernel.org 或發行版的 SRPM 取得原始碼。
清理環境#
make mrproper:清除所有編譯產生的檔案和設定,回到乾淨狀態make clean:只清除編譯產生的目的檔,保留設定
核心功能選擇#
核心的功能配置是編譯中最關鍵的步驟。每個功能有三種狀態:
[*]或<*>:編譯進核心主體<M>:編譯為模組[ ]或< >:不編譯
設定工具#
make menuconfig:基於文字的選單介面(最常用)make oldconfig:基於現有設定檔,只詢問新增的選項make xconfig:圖形介面(需要 Qt)
如果不確定某個選項的作用,最安全的做法是參考發行版目前核心的設定(
/boot/config-$(uname -r))作為起點,在此基礎上進行微調。
編譯與安裝#
編譯步驟#
- 編譯核心:
make bzImage(產生壓縮的核心映像檔) - 編譯模組:
make modules - 安裝模組:
make modules_install(安裝到/lib/modules/核心版本/) - 安裝核心:將核心映像檔複製到
/boot/,更新 GRUB2 設定
建立 initramfs#
新核心安裝後,需要建立對應的 initramfs:
dracut(CentOS 7)或mkinitramfs產生 initramfs 映像檔- initramfs 必須包含掛載根檔案系統所需的模組
更新 Boot Loader#
執行 grub2-mkconfig 重新產生 GRUB2 設定檔,讓新核心出現在開機選單中。
安裝新核心時,不要移除舊核心。如果新核心有問題無法開機,你還可以從 GRUB2 選單選擇舊核心啟動。至少保留一個已知可正常運作的核心作為退路。
單一模組編譯#
有時候你不需要編譯整個核心,只需要為現有核心編譯一個額外的模組(通常是硬體驅動程式)。這比完整的核心編譯簡單得多:
- 取得模組的原始碼
- 確認目前核心的 header 檔案已安裝(
kernel-devel套件) - 編譯模組(通常
make就可以) - 安裝到
/lib/modules/核心版本/下 - 執行
depmod更新模組相依性資料庫 - 用
modprobe載入模組
這是在 Linux 上安裝第三方硬體驅動程式(如 NVIDIA 顯示卡驅動、特殊網卡驅動)的常見方式。DKMS(Dynamic Kernel Module Support)可以在核心更新時自動重新編譯這些第三方模組。
核心編譯的實務觀念#
在現代的 Linux 使用中,自行編譯核心的情境已經大幅減少。但這些知識的價值在於:
- 理解核心與模組的關係,有助於排除驅動程式問題
- 理解核心設定,有助於效能調校
- 理解編譯流程,有助於理解 Linux 發行版是如何建構的
- 在嵌入式系統開發中,客製化核心仍然是必備技能