內核/傳統編譯 - Arch Linux 中文维基

跳至內容

# 內核/傳統編譯

出自 Arch Linux 中文维基
< 内核
翻譯狀態：

- 本文（或部分內容）譯自 Kernel/Traditional compilation，最近一次同步於 2026-03-14，若英文版本有所更改，則您可以幫助同步與翻譯更改的內容。
- 您可以在 ArchWiki 的對應頁面找到本文翻譯的原始修訂歷史。
- 本文可能與英文原文存在出入。

本文介紹從 kernel.org 的原始碼編譯自己的內核。這是一種對所有發行版均適用的傳統方法。取決於你的背景，這也可能比用 ABS 工具編譯內核更複雜。請考慮使用 Arch 構建系統以使重複的編譯任務更加有效和安全。

## 準備

準備編譯時，不需要也不建議使用 root 帳號或用 sudo 等工具獲取 root 權限。

### 安裝核心軟體包

安裝 base-devel包 元軟體包，這個組包含了 make包 和 gcc包 等我們需要的軟體包。參考 Arch 默認內核的 PKGBUILD，同時建議安裝以下軟體包：xmlto包、kmod包、inetutils包, bc包、libelf包、git包、cpio包、perl包、tar包、xz包。

### 創建內核編譯目錄

建議創建單獨的內核編譯目錄，本文使用 `home` 下的 `kernelbuild` 目錄。

    $ mkdir ~/kernelbuild

### 獲取源碼

警告： systemd 需要至少 3.12 版本的內核（cgroups 支持需要 4.2 及以上的版本）。參考 `/usr/share/doc/systemd/README`。

從 https://www.kernel.org 下載源碼，得到你所選的內核版本對應的 tarball (`tar.xz`) 文件。

可以在瀏覽器中簡單地右鍵 `tar.xz` 連結並選擇 `保存連結為` 下載；也可以通過 HTTP、TFTP、Rsync 或者 Git 的各種圖形化或命令行工具下載。

注意：

- 驗證下載到的任何內核 tarball 文件的 PGP 簽名總是好的做法。這樣可以確保它是合法的，並有助於建立信任網絡。參見 kernel.org/signature。

- 對於某些版本（例如 `-rc` 版本），下載的存檔和生成的目錄不會嚴格遵循本頁示例中使用的 `A.B.C` 命名，請根據你的需要進行調整。

下面例子中使用 wget包 下載 A.B.C 內核到 `~/kernelbuild` 目錄:

    $ cd ~/kernelbuild
    $ wget https://cdn.kernel.org/pub/linux/kernel/vA.x/linux-A.B.C.tar.xz

在信任下載的壓縮包之前，你還得驗證下載的正確性。 首先抓取簽名，然後用它來抓取簽名密鑰的指紋，然後使用指紋來獲取實際的簽名密鑰：

    $ wget https://cdn.kernel.org/pub/linux/kernel/vA.x/linux-A.B.C.tar.sign
    $ gpg --list-packets linux-A.B.C.tar.sign | grep -i keyid | awk '{print $NF}' | xargs gpg --recv-keys

注意簽名是為 `tar` 存檔（即擴展名 `.tar`）生成的，而不是為下載的壓縮 `.tar.xz` 文件生成的。 你需要解壓後者而不解壓它。 檢查你是否已安裝 `xz`，然後這樣繼續：

    $ unxz linux-A.B.C.tar.xz
    $ gpg --verify linux-A.B.C.tar.sign linux-A.B.C.tar

如果沒看到"Good signature"就別繼續。

如果在構建目錄中沒使用`wget`，就需要手動將壓縮包移入其中，例如：

    $ mv /path/to/linux-A.B.C.tar.xz ~/kernelbuild/

#### 半官方內核鏡像

一些 kernel.org Git 存儲庫的半官方鏡像由其各自的維護者提供。這些通常比 kernel.org 的版本更新。

- Linus Torvalds 放在 GitHub 上的主線內核

https://github.com/torvalds/linux.git.

- Greg Kroah-Hartman 放在 GitHub 上的穩定分支

https://github.com/gregkh/linux. [1]

### 解壓內核代碼

- 將其解壓後進入源碼目錄:

    $ tar -xvf linux-A.B.C.tar

為了絕對確保不發生權限錯誤，需要運行 chown 將文件夾的所有權轉移給當前用戶。

要將包含其中每個文件的文件夾的所有權轉移，運行 `chown` 命令。

    $ chown -R $USER:$USER linux-A.B.C

文件夾中每個文件的所有權轉移給你了，所以不會遇到任何與權限相關的錯誤。

為了完成準備工作，內核樹需要絕對乾淨；不要覺得解壓後原始碼樹是乾淨的。所以，切換到創建的新內核源目錄，然後運行 `make mrproper` 命令：

    $ cd linux-A.B.C
    $ make mrproper

注意：`make mrproper` 的目標依賴於 `make clean` 的目標，所以沒必要同時執行兩者。參考[2]。

## 配置

這是自定義內核以適應計算機的精確規格的最關鍵步驟。內核配置在 `.config` 文件中設置，其中包括 Kernel modules 的使用情況。正確設置 `.config` 中的選項，你的計算機會獲得最高的運行效率。

注意：現階段無需使用 root 帳戶或 root 權限。

參考使用下面內容可以節省時間：

- 使用 Arch 官方內核的設置(推薦)
- 生成正在運行內核的配置文件和設置（手動，適用於高級用戶但不推薦）

### 導出當前內核設置

這個命令將使用默認的 Arch 內核設置為自定義內核創建一個 `.config` 文件。如果正在運行官方 Arch 內核，你可以在內核源碼目錄中使用以下命令：

    $ zcat /proc/config.gz > .config

也可以在 official Arch Linux kernel 中找到默認配置。

提示：

- 如果你在升級內核，一些選項可能改了或被刪掉了。在這種情況下，在 #Compilation 下運行 `make` 時，它會要求你提供版本之間更改的每個配置選項的答案。要使用默認值而不用一直按Enter，請運行 `make olddefconfig`。

- modprobed-db 可用於從默認 Arch `.config` 中刪除不需要的模塊。獲得 properly populated database 後，運行 `make LSMOD=$HOME/.config/modprobed.db localmodconfig` 從 `modprobed.db` 中刪除所有不存在的模塊。

警告：如果你用當前的 `.config` 文件編譯內核，別忘了在新的 `.config` 中的重命名內核版本，就是"CONFIG_LOCALVERSION"這項。或者用#高級配置中列出的用戶界面之一中的"General Setup > Local version - append to kernel release"更改。如果跳過這一步，就有把當前內核覆蓋的風險。

### 高級配置

提示：如果不想在啟動和關閉時看到很多內核輸出，可以禁用相關的調試選項。

有多種方式可以協助配置內核：

注意：下面列出的工具提供每個內核功能的三個配置選項：`y` 表示啟用，`n` 表示禁用，`m` 表示啟用作為內核模塊（必要時加載）。

- `make nconfig`: 新的命令行 ncurses 界面，用來代替 `menuconfig`。
- `make xconfig`: 用戶友好的圖形界面，需要安裝 Qt。這是推薦的方法，尤其對於沒有經驗的用戶，因為它更容易導航，並且還會顯示每個選項的信息。
- `make gconfig`: 和 xconfig 類似的圖形界面，使用 GTK.

在內核原始碼目錄執行選擇的方法，將生成一個全新的`.config`，可選參數默認是選中的，但是如果有老內核的 `.config` 文件，這些參數不一定會被選中。

改變配置文件並保存。建議在原始碼目錄外備份`.config`,因為你可能需要編譯多次，直到所有的選項都配置正確。如果不確定每個選項的影響，每次編譯只改變少量選項。如果無法啟動新構建的內核，參見這裡查看必須的配置項列表。從liveCD運行`$ lspci -k #`以列出使用中的內核模塊的名字。最重要的是，你必須保留 systemd 需要的 CGROUPS 支持。

從live media運行 `lspci -k #` 會列出正在使用內核模塊的名稱。重中之重，你必須保留cgroup支持，這是systemd的依賴。參閱 Gentoo:Kernel/Gentoo Kernel Configuration Guide 和 Gentoo:Intel#Kernel 或 Gentoo:Ryzen#Kernel（適用於 Intel 或 AMD Ryzen CPU）。

## 編譯

如果希望 gcc包 根據處理器指令集進行優化， 編輯內核目錄下的 `arch/x86/Makefile` (i686) 或 `arch/x86_64/Makefile` (86_64)文件：

- 查找 `Processor type and features > Processor Family` 中設置的處理器系列 `CONFIG_MK8,CONFIG_MPSC,CONFIG_MCORE2,CONFIG_MATOM,CONFIG_GENERIC_CPU`
- 將 cc 調用選項設置為 `-march=native`，例如 `cflags-$(CONFIG_MK8) += $(call cc-option,-march=native)`.

對 32bit 內核，需要編輯 `arch/x86/Makefile_32.cpu` 並設置處理器的 `-march=native`。

編譯時間將從15分鐘到超過一小時不等。這很大程度依賴於選擇了多少選項/模塊和處理器性能。詳情參考 Makeflags。`.config` 配置好之後，在內核目錄運行：

    $ make

提示：為了更快地編譯，可以使用 `-jX` 參數運行 make 以並行編譯，其中 `X` 是整數。最快的編譯通常是通過使用機器中 CPU 核心的數量來實現的； 例如，對於雙核處理器，運行 `make -j2`。 參閱 Makepkg#減少編譯時間。

## 安裝

### 安裝模塊

內核編譯了，它的模塊也隨之而來。首先構建模塊：

    $ make modules

警告：從這裡開始，需要 root 權限執行命令，否則會失敗.

編譯完內核後編譯模塊:

    # make modules_install

這會將編譯後的模塊複製到 `/lib/modules/A.B.C/` 中。 這使得單獨使用的各個內核的模塊保持分離。

提示：如果系統需要正常 Linux 內核外的模塊，需要在定製內核安裝完成之後重新編譯它們。Nvidia 顯卡模塊可以參考 NVIDIA#Custom kernel。

### 拷貝內核到 /boot 目錄

注意：確保已從你的系統架構的目錄複製 `bzImage` 內核文件。見下文。

內核編譯過程將生成該內核的壓縮 `bzImage`，如果沒有，運行：

    make bzImage

必須將這個 bzImage 複製到 `/boot` 目錄並重命名。只要名稱帶有 `vmlinuz-` 前綴，你就可以根據需要命名內核。 在下面的示例中，已安裝並編譯的 A.B.C 內核已被複製並重命名為 `vmlinuz-linuxAB`：

    # cp -v arch/x86/boot/bzImage /boot/vmlinuz-linuxAB

### 製作初始化內存檔

初始化內存檔，是一個在真正的根文件系統可訪問之前被掛載的初始化根目錄文件系統。初始化內存檔（initrd）被綁定到對應的內核，且作為內核啟動過程的一部分被載入。內核將該初始化內存檔（initrd）作為兩階段啟動過程的一部分掛載起來，以載入模塊使得真正的文件系統可用，然後得到真正的根文件系統。初始化內存檔包含實現以上過程的目錄和可執行文件的最小集合，例如用來將內核模塊安裝到內核的insmod工具。對桌面或伺服器Linux系統來說，初始化內存檔(initrd)就是一個臨時的文件系統。其生命周期短暫，僅作為到真正的根文件系統的橋梁。在沒有可變存儲的嵌入式系統中，初始化內存檔就是永久的根文件系統。參考 Initramfs on Wikipedia 和 mkinitcpio。

/boot 中的文件可以取任何名字。然而，為了方便區分，建議採取統一的命名規範，例如使用 `linux<major revision><minor revision>`。

如果你使用了 LILO 引導加載程序且其無法與內核設備映射器驅動連通，你可能需要先運行`modprobe dm-mod`命令。

#### 自動生成

可以複製和修改現有的 mkinitcpio preset，以便可以按照與官方內核相同的方式生成自定義內核 initramfs image。 這在重新編譯內核（例如更新時）時會節省很多時間。 在下面的示例中，將為上面安裝的內核A.B.C複製並修改庫存 Arch 內核的預設文件。

首先，複製現有的預設文件，將其重命名為與複製 `bzImage` 時指定為 `/boot/vmlinuz-` 後綴的自定義內核的名稱相匹配：

    # cp /etc/mkinitcpio.d/linux.preset /etc/mkinitcpio.d/linuxAB.preset

其次，編輯文件並針對自定義內核進行修改。注意 `ALL_kver=` 參數也與複製 `bzImage` 時指定的自定義內核的名稱匹配：

    /etc/mkinitcpio.d/linuxAB.preset

    ...
    ALL_kver="/boot/vmlinuz-linuxAB"
    ...
    default_image="/boot/initramfs-linuxAB.img"
    ...
    fallback_image="/boot/initramfs-linuxAB-fallback.img"

最後，生成 initramfs 映像：

    # mkinitcpio -p linuxAB

#### 手動方法

不使用 preset 文件，可以用 mkinitcpio 手動生成：

    # mkinitcpio -k <kernelversion> -g /boot/initramfs-<file name>.img

- `-k` (--kernel <kernelversion>): 生成 initramfs image 的內核版本. `<kernelversion>` 需要和內核原始碼目錄和`/usr/lib/modules/`下的模塊目錄一致.
- `-g` (--generate <filename>): 要生成的 initramfs 文件。

例如，上面安裝的A.B.C自定義內核的命令為：

    # mkinitcpio -k A.B.C -g /boot/initramfs-linuxAB.img

### 拷貝 System.map

`System.map` 文件並非 Linux 啟動所必須的。它包含一張該次構建的內核的標識符之列表（例如函數名，變量名等等）和它們相應的地址。該「標識符到地址的映射」是用於：

- 某些進程，像 klogd, ksymoops 等
- OOPS 處理程序，當內核崩潰出錯信息釋放到屏幕時（例如類似於內核在某個函數中崩潰了的信息）。

提示：UEFI 分區使用 FAT32 文件系統，不支持軟連結。

如果 `/boot` 支持軟連結（即不是 FAT32），將 `System.map` 複製到 `/boot`, 然後創建 `/boot/System.map` 軟連結到 `/boot/System.map-YourKernelName`:

    # cp System.map /boot/System.map-YourKernelName
    # ln -sf /boot/System.map-YourKernelName /boot/System.map

如果 `/boot` 是不支持軟連結的 FAT32，則需要將第二條命令換成 cp 來複製文件。

完成以上所有步驟之後，你的/boot目錄中應該多出以下三個文件和一個軟連結：

- Kernel: `vmlinuz-YourKernelName`
- Initramfs: `Initramfs-YourKernelName.img`
- System Map: `System.map-YourKernelName`
- System.map 軟連結（或者復件）

## 引導加載程序設置

在你的引導加載程序（bootloader）配置文件中為你神奇的新內核添加一個入口。範例見GRUB, LILO, GRUB2 或 Syslinux。

提示：內核源碼包含一個用於自動化 LILO 安裝過程的腳本：如果你正在使用其他引導加載程序，可以安全地忽略它。
分類：​

- 內核

內核/傳統編譯
新增話題