Kernel/Traditional compilation

出自 ArchWiki

本文介绍了如何从 kernel.org 源码构建自定义内核。这种编译内核的方法是所有发行版通用的传统方法。根据您的背景,它可能比使用 Kernel/Arch 构建系统 更为复杂。请考虑 Arch 构建系统 工具的开发和维护是为了使可重复的编译任务高效且安全。

准备工作

内核准备工作没有必要(也不建议)使用 root 账户或 root 权限(即通过 sudo)。

安装核心软件包

安装 base-devel 元软件包,它会拉取必要的软件包,例如 makegcc。还建议安装以下软件包,它们在默认 Arch 内核 PKGBUILD 中列出:xmltokmodinetutilsbclibelfgitcpioperltarxz

创建内核编译目录

建议为您的内核创建一个单独的构建目录。在本例中,目录 kernelbuild 将在 home 目录中创建

$ mkdir ~/kernelbuild

下载内核源码

警告: systemd 至少需要内核版本 3.12(对于统一 cgroups 层次结构支持,则需要 4.2 或更高版本)。有关更多信息,请参见 /usr/share/doc/systemd/README

https://linuxkernel.org.cn 下载内核源码。这应该是您选择的内核的 tarball (.tar.xz) 文件。

可以通过在浏览器中右键单击 tar.xz 链接并选择 Save Link As... 来下载,或者通过使用 HTTP、TFTPRsyncGit 的其他图形或命令行工具来下载。

注意
  • 最好验证任何下载的内核 tarball 的 PGP 签名。这可以确保其合法性,并有助于构建信任网络。请参见 kernel.org/signature
  • 对于某些版本(例如 -rc 版本),下载的存档和生成的目录将不严格遵循此页面示例中使用的 A.B.C 命名,请根据您的需要进行调整。

在以下命令行命令中,wget 已安装,并在 ~/kernelbuild 目录中使用以获取内核 A.B.C

$ 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,则需要将 tarball 移动到其中,例如

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

半官方内核镜像

本文或章节需要扩充。

原因: 与其使用半官方镜像,不如使用 官方 git bundles 可以更快地完成初始克隆。(在 Talk:Kernel/Traditional compilation 中讨论)

kernel.org Git 仓库的一些半官方镜像由其各自的维护者提供。这些镜像的克隆速度往往比 kernel.org 快。

解包内核源码

在构建目录中,解包内核 tarball

$ 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
注意: mrproper Make 目标依赖于 clean 目标,因此,没有必要同时执行两者。有关参考,请参见 [2]

内核配置

这是自定义默认内核以反映您计算机的精确规格的最关键步骤。内核配置在其 .config 文件中设置,其中包括 内核模块 的使用。通过正确设置 .config 中的选项,您的内核和计算机将以最高效的方式运行。

注意: 在此阶段没有必要使用 root 账户或 root 权限。

您可以执行以下两件事的组合

  • 使用来自官方内核的默认 Arch 设置(推荐)
  • 手动配置内核选项(可选,高级且不推荐)

默认 Arch 配置

此方法将使用默认 Arch 内核设置为自定义内核创建 .config 文件。如果正在运行 stock Arch 内核,则可以在自定义内核源码目录中使用以下命令

$ zcat /proc/config.gz > .config

否则,可以在 官方 Arch Linux 内核 软件包中在线找到默认配置。

提示
  • 如果您正在升级内核,则某些选项可能已更改或已删除。在这种情况下,当在 #编译 下运行 make 时,系统会要求您为版本之间已更改的每个配置选项提供答案。要接受默认值而不提示,请运行 make olddefconfig
  • modprobed-db 可用于从默认 Arch .config 中剥离不需要的模块。一旦获得 正确填充的数据库,运行 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 menuconfig:命令行 ncurses 界面,已被 nconfig 取代
  • make nconfig:用于命令行的较新的 ncurses 界面
  • make xconfig:用户友好的图形界面,需要安装 packagekit-qt5 作为依赖项。这是推荐的方法 - 特别是对于经验不足的用户 - 因为它更容易导航,并且还显示有关每个选项的信息。
  • make gconfig: 图形化配置,类似于 xconfig,但使用 GTK。这需要 gtk2glib2libgladeAUR

选择的方法应在内核源代码目录内运行,所有方法都将创建一个新的 .config 文件,或者覆盖现有的文件(如果存在)。所有可选配置都将自动启用,但任何较新的配置选项(即使用较旧内核的 .config)可能不会自动选择。

完成更改后,保存 .config 文件。最好在源代码目录之外制作一个备份副本。您可能需要多次执行此操作,直到获得所有正确的选项。

如果不确定,仅在编译之间更改几个选项。如果您无法启动新构建的内核,请参阅此处列出的必要项目。

从 live media 运行 lspci -k # 会列出正在使用的内核模块的名称。最重要的是,您必须保持 cgroups 支持。这对于 systemd 是必要的。有关更详细的信息,请参阅 Gentoo:Kernel/Gentoo Kernel Configuration GuideGentoo:Intel#KernelGentoo:Ryzen#Kernel,了解 Intel 或 AMD Ryzen 处理器。

编译

提示: 如果您想让 gcc 针对您的处理器的指令集进行优化,请编辑内核源代码目录内的 arch/x86/Makefile
  • 查找您在 Processor type and features > Processor Family 中选择的 CONFIG_MK8,CONFIG_MPSC,CONFIG_MCORE2,CONFIG_MATOM,CONFIG_GENERIC_CPU
  • call cc-options 标志从 -march=native 更改为您在 Processor Family 中选择的标志,例如 cflags-$(CONFIG_MK8) += $(call cc-option,-march=native)。这可能是使用 -march=native 进行编译的最佳方式,因为它有效。

编译时间将从短短的十五分钟到超过一个小时不等,具体取决于您的内核配置和处理器能力。一旦为自定义内核设置了 .config 文件,请在源代码目录中运行以下命令进行编译

$ make
提示: 要更快地编译,make 可以与 -jX 参数一起运行,其中 X 是并行作业的整数数量。通常使用机器中 CPU 核心的数量可以获得最佳结果;例如,对于双核处理器,运行 make -j2。有关更多信息,请参阅 Makepkg#Improving build times

安装

安装模块

内核编译完成后,必须安装其模块。首先构建模块

$ make modules

然后安装模块。以 root 用户身份或使用 root 权限,运行以下命令执行此操作

# make modules_install

这会将编译后的模块复制到 /lib/modules/A.B.C/ 中。这会将各个内核使用的模块分开。

提示: 如果您的系统需要未与常规 Linux 内核一起分发的模块,则需要在自定义内核完成后为其编译这些模块。此类模块通常是您为正在运行的系统显式单独安装的模块。有关示例,请参阅 NVIDIA#Custom kernel

将内核复制到 /boot 目录

注意: 确保已从适用于您的系统架构的目录复制了 bzImage 内核文件。请参阅下文。

内核编译过程将生成该内核的压缩 bzImage (big zImage),如果未生成,您可能需要运行

make bzImage

此文件必须复制到 /boot 目录并在过程中重命名。只要名称以 vmlinuz- 为前缀,您就可以随意命名内核。在下面的示例中,已复制并重命名已安装和编译的 A.B.C 内核为 vmlinuz-linuxAB

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

制作初始 RAM 磁盘

注意: 您可以随意命名生成 initramfs 镜像文件时的名称。但是,建议使用 linuxmajor_revisionminor_revision 约定。此约定将使维护多个内核、定期使用 mkinitcpio 和构建第三方模块更加容易。
提示: 如果您正在使用 LILO 引导加载程序,并且它无法与内核设备映射器驱动程序通信,则必须首先运行 modprobe dm-mod

如果您不知道制作初始 RAM 磁盘是什么,请参阅 Wikipedia 上的 Initramfsmkinitcpio

自动预设方法

可以复制和修改现有的 mkinitcpio 预设,以便可以像为官方内核一样生成自定义内核 initramfs 镜像。这在打算重新编译内核(例如,在更新的情况下)时很有用。在下面的示例中,将复制并修改用于 stock Arch 内核的预设文件,以用于上面安装的内核 A.B.C

首先,复制现有的预设文件,将其重命名为与自定义内核的名称匹配,该名称在复制 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

手动方法

除了使用预设文件外,mkinitcpio 也可以用于手动生成 initramfs 文件。命令的语法是

# mkinitcpio -k kernel_version -g /boot/initramfs-file_name.img
  • -k (--kernel kernel_version): 指定在生成 initramfs 镜像时要使用的模块。kernel_version 名称将与其模块目录的名称相同,该目录位于 /usr/lib/modules/ 中(或者,可以使用内核镜像的路径)。
  • -g (--generate file_name): 指定要在 /boot 目录中生成的 initramfs 文件的名称。同样,建议使用上面提到的命名约定。

例如,上面安装的 A.B.C 自定义内核的命令将是

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

复制 System.map

启动 Linux 不需要 System.map 文件。它是一种内核特定构建中函数的“电话簿”列表。System.map 包含内核符号(即函数名称、变量名称等)及其对应地址的列表。此“符号名到地址的映射”被以下项使用

  • 一些进程,如 klogd、ksymoops 等。
  • 当必须在内核崩溃期间将信息转储到屏幕时(即,类似崩溃发生在哪个函数中的信息),由 OOPS 处理程序使用。
提示: EFI 系统分区使用 FAT32 格式化,它不支持符号链接。

如果您的 /boot 位于支持符号链接的文件系统上(即不是 FAT32),请将 System.map 复制到 /boot,并将内核名称附加到目标文件。然后创建一个从 /boot/System.map 指向 /boot/System.map-linuxAB 的符号链接

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

完成上述所有步骤后,您应该在 /boot 目录中拥有以下 3 个文件和 1 个软符号链接以及任何其他先前存在的文件

  • 内核:vmlinuz-linuxAB
  • Initramfs:initramfs-linuxAB.img
  • System Map:System.map-linuxAB
  • System Map 内核符号链接:System.map (它符号链接到 System.map-linuxAB)

引导加载程序配置

在引导加载程序的配置文件中为您的新内核添加一个条目。有关可能的引导加载程序、其 wiki 文章和其他信息,请参阅 Arch boot process#Feature comparison

提示: 内核源代码包含一个脚本来自动化 LILO 的过程:如果您正在使用其他引导加载程序,则可以安全地忽略它。

另请参阅