Linux 软件包包含 Linux 内核。
构建内核需要三步 —— 配置、编译、安装。阅读内核源代码树中的 README
文件,了解不同于本手册的内核配置方法。
运行以下命令,准备编译内核:
make mrproper
该命令确保内核源代码树绝对干净,内核开发组建议在每次编译内核前运行该命令。尽管内核源代码树在解压后应该是干净的,但这并不完全可靠。
有多种配置内核选项的方法。例如,通常我们通过目录驱动的界面完成这一工作:
make menuconfig
以上命令中可选的 make 环境变量及含义:
LANG=<host_LANG_value>
LC_ALL=
它们根据宿主使用的 locale 建立 locale 设定。在 UTF-8 Linux 文本终端下,有时必须这样做才能正确绘制基于 ncurses 的配置菜单接口。
在这种情况下,一定要将 <host_LANG_value>
替换成宿主环境中的 $LANG
变量值。您也可以使用宿主环境中
$LC_ALL
或 $LC_CTYPE
的值代替。
这会启动 ncurses 目录驱动的界面。如果希望了解其他 (图形) 界面,可以输入 make help。
阅读 https://www.linuxfromscratch.org/hints/downloads/files/kernel-configuration.txt 了解关于内核配置的一般信息。BLFS 包含一些关于 LFS 之外的软件包需要的特定内核配置的信息,位于https://www.linuxfromscratch.org/blfs/view/stable-systemd/longindex.html#kernel-config-index。另外在 http://www.kroah.com/lkn/ 也有一些关于配置和构建内核的信息。
一个较好的初始内核配置可以通过运行 make defconfig 获得。它会考虑您的当前系统体系结构,将基本内核配置设定到较好的状态。
一定要按照以下列表启用/禁用/设定其中列出的内核特性,否则系统可能不能正常工作,甚至根本无法引导:
General setup --> [ ] Compile the kernel with warnings as errors [CONFIG_WERROR] [ ] Auditing Support [CONFIG_AUDIT] < > Enable kernel headers through /sys/kernel/kheaders.tar.xz [CONFIG_IKHEADERS] [*] Control Group support [CONFIG_CGROUPS] [*] Memory controller [CONFIG_MEMCG] [ ] Enable deprecated sysfs features to support old userspace tools [CONFIG_SYSFS_DEPRECATED] [*] Configure standard kernel features (expert users) [CONFIG_EXPERT] ---> [*] open by fhandle syscalls [CONFIG_FHANDLE] CPU/Task time and stats accounting ---> [*] Pressure stall information tracking [CONFIG_PSI] General architecture-dependent options ---> [*] Enable seccomp to safely compute untrusted bytecode [CONFIG_SECCOMP] Networking support ---> Networking options ---> <*> The IPv6 protocol [CONFIG_IPV6] Device Drivers ---> Firmware Drivers ---> [*] Export DMI identification via sysfs to userspace [CONFIG_DMIID] Graphics support ---> Frame buffer Devices ---> [*] Support for frame buffer devices ---- Generic Driver Options ---> [ ] Support for uevent helper [CONFIG_UEVENT_HELPER] [*] Maintain a devtmpfs filesystem to mount at /dev [CONFIG_DEVTMPFS] [*] Automount devtmpfs at /dev, after the kernel mounted the rootfs [CONFIG_DEVTMPFS_MOUNT] Firmware Loader ---> [ ] Enable the firmware sysfs fallback mechanism [CONFIG_FW_LOADER_USER_HELPER] File systems ---> [*] Inotify support for userspace [CONFIG_INOTIFY_USER] Pseudo filesystems ---> [*] Tmpfs POSIX Access Control Lists [CONFIG_TMPFS_POSIX_ACL]
如果在构建 64 位系统,还需要启用一些特性。如果使用 menuconfig 进行配置,需要首先启用 CONFIG_PCI_MSI
,然后启用 CONFIG_IRQ_REMAP
,最后启用 CONFIG_X86_X2APIC
,这是因为只有选定了一个选项的所有依赖项后,该选项才会出现。
Processor type and features ---> [*] Support x2apic [CONFIG_X86_X2APIC] Memory Management options ---> [ ] Enable userfaultfd() system call [CONFIG_USERFAULTFD] Device Drivers ---> [*] PCI Support ---> [CONFIG_PCI] [*] Message Signaled Interrupts (MSI and MSI-X) [CONFIG_PCI_MSI] [*] IOMMU Hardware Support ---> [CONFIG_IOMMU_SUPPORT] [*] Support for Interrupt Remapping [CONFIG_IRQ_REMAP]
尽管 “The IPv6 Protocol” (IPv6 协议支持) 并不是严格要求的,但是 systemd 开发者强烈推荐启用它。
如果您的硬件支持 UEFI,且您希望通过 UEFI 引导 LFS 系统,则您需要按照 BLFS 页面 的说明,调整一些内核配置选项。
上述配置选项的含义:
Compile the
kernel with warnings as errors
如果使用了和内核开发者不同的编译器和/或配置,启用该选项可能导致构建失败。
Enable kernel
headers through /sys/kernel/kheaders.tar.xz
启用该选项将会导致构建内核需要 cpio。LFS 没有安装 cpio。
Support for
uevent helper
如果启用了该选项,它可能干扰 Udev/Eudev 的设备管理。
Maintain a
devtmpfs
该选项会使内核自动创建设备节点,即使 Udev 没有运行。Udev 之后才在这些设备节点的基础上运行,管理它们的访问权限并为它们建立符号链接。所有 Udev/Eudev 用户都需要启用该选项。
Automount
devtmpfs at /dev
该选项使得内核在切换到根文件系统之后,执行 init 前,将内核获知的设备信息挂载到 /dev。
Support
x2apic
支持以 x2APIC 模式运行 64 位 x86 处理器的中断控制器。64 位 x86 系统的固件可能启用了 x2APIC,此时未启用该选项的内核在引导时会发生内核恐慌。该选项在固件禁用 x2APIC 时没有作用,但无害。
Enable
userfaultfd() system call
如果启用该选项,则会暴露一项在 Linux-5.19.2 中尚未解决的安全缺陷。禁用该选项以避免安全缺陷。userfaultfd() 系统调用并未被 LFS 或 BLFS 中的任何组件使用。
某些情况下,make oldconfig
更为合适。阅读 README
文件了解更多信息。
如果希望的话,也可以将宿主系统的内核配置文件 .config
拷贝到解压出的 linux-5.19.2
目录
(前提是可以找到该文件)。然而我们不推荐这样做,一般来说,浏览整个配置目录,并从头创建内核配置是更好的选择。
编译内核映像和模块:
make
如果要使用内核模块,可能需要在 /etc/modprobe.d
中写入模块配置。讨论模块和内核配置的信息位于第 9.3 节 “设备和模块管理概述”和
linux-5.19.2/Documentation
目录下的内核文档中。另外 modprobe.d(5)
也可以作为参考。
如果内核配置使用了模块,安装它们:
make modules_install
在内核编译完成后,需要进行额外步骤完成安装,一些文件需要拷贝到 /boot
目录中。
如果宿主系统有单独的 /boot 分区,需要将这些文件拷贝到该分区中。最简单的方法是将宿主系统的 /boot (在 chroot
之外) 绑定到 /mnt/lfs/boot 再拷贝文件,在宿主系统中,以 root
身份执行:
mount --bind /boot /mnt/lfs/boot
指向内核映像的路径可能随机器平台的不同而变化。下面使用的文件名可以依照您的需要改变,但文件名的开头应该保持为 vmlinuz,以保证和下一节描述的引导过程自动设定相兼容。下面的命令假定是机器是 x86 体系结构:
cp -iv arch/x86/boot/bzImage /boot/vmlinuz-5.19.2-lfs-11.2-systemd
System.map
是内核符号文件,它将内核 API
的每个函数入口点和运行时数据结构映射到它们的地址。它被用于调查分析内核可能出现的问题。执行以下命令安装该文件:
cp -iv System.map /boot/System.map-5.19.2
内核配置文件 .config
由上述的 make menuconfig
步骤生成,包含编译好的内核的所有配置选项。最好能将它保留下来以供日后参考:
cp -iv .config /boot/config-5.19.2
安装 Linux 内核文档:
install -d /usr/share/doc/linux-5.19.2 cp -r Documentation/* /usr/share/doc/linux-5.19.2
需要注意的是,在内核源代码目录中可能有不属于 root 的文件。在以 root 身份解压源代码包时 (就像我们在 chroot 环境中所做的那样),这些文件会获得它们之前在软件包创建者的计算机上的用户和组 ID。这一般不会造成问题,因为在安装后通常会删除源代码目录树。然而,Linux 源代码目录树一般会被保留较长时间,这样创建者当时使用的用户 ID 就可能被分配给本机的某个用户,导致该用户拥有内核源代码的写权限。
之后在 BLFS 中安装软件包时往往需要修改内核配置。因此,和其他软件包不同,我们在安装好内核后可以不移除源代码树。
如果要保留内核源代码树,对内核源代码目录运行 chown -R
0:0 命令,以保证 linux-5.19.2
目录中所有文件都属于 root。
有的内核文档建议创建符号链接 /usr/src/linux
指向内核源代码目录,这仅仅适用于 2.6 系列之前的内核。在 LFS 系统上绝对不要创建它,因为在构建完基本 LFS
系统后,它可能在您构建其他软件包时引起问题。
在系统 include
目录 (即 /usr/include
) 中的内核头文件应该总是与构建 Glibc 时使用的内核头文件一致,即保持为第 5.4 节 “Linux-5.19.2
API 头文件”中安装的净化头文件。换句话说,永远不要用原始内核头文件,或其他版本内核的净化头文件替换它们。
多数情况下 Linux 内核模块可以自动加载,但有时需要指定加载顺序。负责加载内核模块的程序 modprobe 和 insmod 从 /etc/modprobe.d
下的配置文件中读取加载顺序,例如,如果 USB 驱动程序
(ehci_hcd、ohci_hcd 和 uhci_hcd) 被构建为模块,则必须按照先加载 echi_hcd,再加载
ohci_hcd 和 uhci_hcd 的正确顺序,才能避免引导时出现警告信息。
为此,执行以下命令创建文件 /etc/modprobe.d/usb.conf
:
install -v -m755 -d /etc/modprobe.d
cat > /etc/modprobe.d/usb.conf << "EOF"
# Begin /etc/modprobe.d/usb.conf
install ohci_hcd /sbin/modprobe ehci_hcd ; /sbin/modprobe -i ohci_hcd ; true
install uhci_hcd /sbin/modprobe ehci_hcd ; /sbin/modprobe -i uhci_hcd ; true
# End /etc/modprobe.d/usb.conf
EOF