Linux 软件包包含 Linux 内核。
构建内核需要三步 —— 配置、编译、安装。 阅读内核源代码树中的 README
文件, 了解不同于本手册的内核配置方法。
运行以下命令,准备编译内核:
make mrproper
该命令确保内核源代码树绝对干净, 内核开发组建议在每次编译内核前运行该命令。 尽管内核源代码树在解压后应该是干净的,但这并不完全可靠。
下面通过菜单界面配置内核,阅读 http://www.linuxfromscratch.org/hints/downloads/files/kernel-configuration.txt 了解关于内核配置的一般信息。 BLFS 的某些软件包需要特定内核配置,阅读 http://www.linuxfromscratch.org/blfs/view/8.3/longindex.html#kernel-config-index 了解它们。另外在 http://www.kroah.com/lkn 也有一些关于配置和构建内核的信息。
一个较好的初始内核配置可以通过运行 make defconfig 获得。 它会考虑您的当前系统体系结构,将基本内核配置设定到较好的状态。
一定要按照以下列表启用/禁用/设定其中列出的内核特性, 否则系统可能不能正常工作,甚至根本无法引导:
Device Drivers ---> Generic Driver Options ---> [ ] Support for uevent helper [CONFIG_UEVENT_HELPER] [*] Maintain a devtmpfs filesystem to mount at /dev [CONFIG_DEVTMPFS] Kernel hacking ---> Choose kernel unwinder (Frame pointer unwinder) ---> [CONFIG_UNWINDER_FRAME_POINTER]
There are several other options that may be desired depending on the requirements for the system. For a list of options needed for BLFS packages, see the BLFS Index of Kernel Settings (http://www.linuxfromscratch.org/blfs/view/8.3/longindex.html#kernel-config-index).
如果您的硬件平台使用 UEFI,则 make defconfig 命令也会自动加入一些 EFI 相关的内核选项。
为了允许从宿主系统的 UEFI 引导环境引导 LFS 内核, 您必须选择一个内核选项:
Processor type and features ---> [*] EFI stub support [CONFIG_EFI_STUB]
在 LFS 中管理 UEFI 环境的较完整说明包含在 lfs-uefi.txt 中, 它位于 http://www.linuxfromscratch.org/hints/downloads/files/lfs-uefi.txt。
lfs-uefi.txt 的内容较老,译者维护了它的一份更新版本, 见 http://svn.linuxfromscratch.org/hints/trunk/lfs-uefi-20180409.txt 。
上述配置选项的含义:
Support for
uevent helper
如果启用了该选项,它可能干扰 Udev/Eudev 的设备管理。
Maintain a
devtmpfs
该选项会使内核自动创建设备节点,即使 Udev 没有运行。 Udev 之后才在这些设备节点的基础上运行, 管理它们的访问权限并为它们建立符号链接。 所有 Udev/Eudev 用户都需要启用该选项。
make menuconfig
以上命令中可选的 make 环境变量及含义:
LANG=<host_LANG_value>
LC_ALL=
它们根据宿主使用的 locale 建立 locale 设定。 在 UTF-8 Linux 文本终端下,有时必须这样做才能正确绘制 基于 ncurses 的配置菜单接口。
在这种情况下,一定要将 <host_LANG_value>
替换成宿主环境中的 $LANG
变量值。您也可以使用宿主环境中
$LC_ALL
或 $LC_CTYPE
的值代替。
某些情况下,make oldconfig
更为合适。 阅读 README
文件了解更多信息。
如果希望的话,也可以将宿主系统的内核配置文件 .config
拷贝到解压出的 linux-4.18.5
目录(前提是可以找到该文件)。然而我们不推荐这样做, 一般来说,浏览整个配置目录,并从头创建内核配置是更好的选择。
编译内核映像和模块:
make
如果要使用内核模块,可能需要在 /etc/modprobe.d
中写入模块配置。讨论模块和内核配置的信息位于 第 7.3 节 “设备和模块管理概述” 和
linux-4.18.5/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-4.18.5-lfs-8.3
System.map
是内核符号文件, 它将内核 API
的每个函数入口点和运行时数据结构映射到它们的地址。 它在调查分析内核出现的问题时被使用。执行以下命令安装该文件:
cp -iv System.map /boot/System.map-4.18.5
make menuconfig
生成的内核配置文件 .config
包含编译好的内核的所有配置选项。
最好能将它保留下来以供日后参考:
cp -iv .config /boot/config-4.18.5
安装 Linux 内核文档:
install -d /usr/share/doc/linux-4.18.5 cp -r Documentation/* /usr/share/doc/linux-4.18.5
需要注意的是,在内核源代码目录中可能有不属于 root 的文件。在以 root 身份解压源代码包时(就像我们在 chroot 环境中所做的那样), 这些文件会获得它们之前在软件包创建者的计算机上的用户和组 ID。 这一般不会造成问题,因为在安装后通常会删除源代码目录树。 然而,Linux 源代码目录树一般会被保留较长时间, 这样创建者当时使用的用户 ID 就可能被分配给本机的某个用户, 导致该用户拥有内核源代码的写权限。
之后在 BLFS 中安装软件包时往往需要修改内核配置。 因此,和其他软件包不同,我们在安装好内核后可以不移除源代码树。
如果要保留内核源代码树,对目录 linux-4.18.5
执行
chown -R
0:0,以保证其中所有文件都属于 root。
有的内核文档建议创建符号链接 /usr/src/linux
指向内核源代码目录,这仅仅适用于 2.6 系列之前的内核。 在 LFS 系统上绝对不要创建它, 因为在构建完基本 LFS
系统后,它可能在您构建其他软件包时引起问题。
在系统 include
目录(即 /usr/include
中的内核头文件应该总是与构建 Glibc 时使用的内核头文件一致,即保持为 第 6.7 节 “Linux-4.18.5
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