配置引导

5.2.1 创建/etc/fstab 文件

/etc/fstab 文件的作用是让其他程序确定存储设备的默认挂载点、挂载参数和检查信息(例如完整性检测)。 以下是笔者的 fstab 文件为例讲解,请根据自己的分区情况进行更改。一个取巧的方法是参考宿主机中的 fstab 文件,进行更改。

cat > /etc/fstab << "EOF"
# Begin /etc/fstab

# file system  mount-point  type     options             dump  fsck
#                                                                      order

/dev/sda5     /            ext4    defaults                 1     1
/dev/sda1     /boot        ext2    defaults                0     2
proc           /proc        proc     nosuid,noexec,nodev  0     0
sysfs          /sys         sysfs    nosuid,noexec,nodev  0     0
devpts         /dev/pts     devpts   gid=5,mode=620       0     0
tmpfs          /run         tmpfs    defaults               0     0
devtmpfs       /dev         devtmpfs mode=0755,nosuid    0     0

# End /etc/fstab
EOF

其中的 sda1、sda5 和 ext2、ext4 请使用适当的值替换。关于文件中 6 个字段的含义,请查看 man 5 fstab1

基于 MS-DOS 或者是来源于 Windows 的文件系统(例如:vfat,ntfs,smbfs,cifs,iso9660,udf)需要在挂载选项中添加 iocharset,才能让非 ASCII 字符的文件名正确解析。此选项的值应该与语言区域设置的值相同,以便让内核能正确处理。此选项在相关字符集定义已为内核内建或编译为模块时生效(在文件系统→本地语言支持中查看)。此外,vfat 和 smbfs 还需启用 codepage,同样也是为了解决文字的正常显示问题。例如,想要挂载 USB 闪存设备,zh-CN.GBK 用户需要在/etc/fstab 中添加以下挂载选项:

noauto,user,quiet,showexec,iocharset=gbk,codepage=936

对于 zh_CN.UTF-8 用户的对应选项是:

noauto,user,quiet,showexec,iocharset=utf8,codepage=936

需要注意的是,iocharset 默认值是 iso8859-1(其保证文件系统大小写敏感),而 utf8 这个参数告知内核使用 UTF-8 转换文件名,以便可以在 UTF-8 语言环境中解释它们。 此外,还有可能在内核的配置过程中就指定一些文件系统的默认 codepage 和 iocharset 值。相关参数有“默认 NLS 选项”(CONFIG_NLS_DEFAULT),“默认远程 NLS 选项”(CONFIG_SMB_NLS_DEFAULT),“FAT 默认代码页”(CONFIG_FAT_DEFAULT_CODEPAGE),和“FAT 默认 IO 字符集”(CONFIG_FAT_DEFAULT_IOCHARSET)。不过,无法在内核编译阶段指定 ntfs 文件系统的设置。 另外,一些硬盘类型在遇到电源故障时,假如在/etc/fstab 中使用 barrier=1 这个挂载选项,则会让 ext3 文件系统的数据更加安全。如需检查磁盘是否支持此选项,请运行 hdparm。例如:

hdparm -I /dev/sda | grep NCQ

如果有输出内容,则代表选项可用。

注意:基于逻辑卷管理(LVM)的分区不可使用 barrier 选项。

5.2.2 使用 GRUB 设置启动过程

这一步可以算是临门一脚,也是最容易功亏一篑的一步,因为这步配置问题会直接导致系统无法启动。这也是为什么笔者非常推荐使用虚拟机来完成构建的原因。如果是实机环境,就不得不面临使用 CD 或者 USB 来救场的情况。不过需要明确的是这一步出错绝没有严重到需要推倒重来的地步,出现无法引导的情况只需要通过 USB 等的方法挂载分区,重新配置 Grub 即可。

GRUB 对于硬盘和分区,自身有一套命名规则 (hdn,m),其中 n 是硬盘数,m 是分区号。硬盘数 N 从 0 开始计数,分区数需要区别对待——主分区从 1 开始计数而扩展分区从 5 开始计数。需要注意的是,和早期版本相比,计数方式有所变化。例如,分区 sda1 是 (hd0,1),sdb3 是 (hd1,3)。Linux 下,并不将 CD-ROM 设备假想为硬盘。例如,就算已有 CD 设备挂载为 hdb,第二块硬盘挂载为 hdc,Grub 依旧将第二块硬盘称为 (hd1)。

GRUB 会将一些数据写入硬盘的第一个物理扇区。这一部分不属于任何一个操作系统,在启动时,该部分数据激活,然后寻找 Grub 的模块,GRUB 模块的默认位置为/boot/grub/。

引导分区的位置会影响配置和使用。

一种建议是使用一个独立的小分区(建议大小 100MB)专用于存放引导信息,则每一个发行版,不论是 LFS 还是其他的商业发行版都能访问相同的引导文件,而且任何已经启动的系统都能访问该分区中的内容。如果你选择这么做,你需要挂载这个独立分区,移动所有的文件从当前的/boot 目录(比如说你上一节刚编译的 Linux 内核)到新的分区。你然后要卸载这个新分区,重新挂载它为/boot。如果你这么做,一定要更新/etc/fstab。本书采用的就是这种方式 。 另一种则是直接使用当前的 lfs 分区,但这种方式在配置多系统启动的时候比较麻烦。

以上两种不同的方式需要注意的分区也不同,如果你使用单独的分区,需要知道引导分区的磁盘位置;如果使用当前的 lfs 分区,也需要明确当前分区的磁盘位置,以下假定根分区(或者是磁盘分区)是 sda2。

将 GRUB 文件安装到/boot/grub 然后设置引导扇区:

grub-install /dev/sda

如果系统是通过 UEFI 引导的,grub-install 将会尝试安装 x86_64-efi 的文件,但是这些文件并未在第 4 章中安装。所以在在这种情况下,请在上述命令后面追加--target i386-pc。 创建 GRUB 配置文件:

cat > /boot/grub/grub.cfg << "EOF"
# Begin /boot/grub/grub.cfg
set default=0
set timeout=5

insmod ext2
set root=(hd0,1)

menuentry "GNU/Linux, Linux 5.2.8-lfs-9.0" {
        linux   /boot/vmlinuz-5.2.8-lfs-9.0 root=/dev/sda2 ro
}
EOF

请参照上述对于 Grub 的介绍,并根据自己的分区情况、是否使用 UEFI 等因素,修改自己的 grub.cfg 文件。

1

fsck 列的数值来决定需要检查的文件系统的检查顺序。允许的数字是 0, 1,和 2。根目录应当获得最高的优先权 1,其他所有需要被检查的设备设置为 2。0 表示设备不会被 fsck 所检查。