使 LFS 系统可引导
创建 /etc/fstab 文件
执行以下命令创建
/etc/fstab
/etc/fstab
cat > /etc/fstab << "EOF"
# Begin /etc/fstab
# 文件系统 挂载点 类型 选项 转储 检查
# 顺序
#/dev/<xxx> / <fff> defaults 1 1
#/dev/<yyy> swap swap pri=1 0 0
/dev/disk/by-uuid/81368941-bd96-4539-bf8e-7215d532a872 / xfs defaults 0 1
/dev/disk/by-uuid/DA73-A40D /boot/efi vfat defaults 0 0
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
tmpfs /dev/shm tmpfs nosuid,nodev 0 0
cgroup2 /sys/fs/cgroup cgroup2 nosuid,noexec,nodev 0 0
# End /etc/fstab
EOF
备注
这里配置 <xxx>、<yyy> 和 <fff>
参考之前 LFS分区( mbp15_late_2013)
Linux内核
cd /sources
kernel_VERSION=6.10.5
tar xf linux-${kernel_VERSION}.tar.xz
cd linux-${kernel_VERSION}
# 准备编译内核,先确保内核源代码完全干净
make mrproper
# 执行获得一个初始化内核配置 .config
# Default configuration is based on 'x86_64_defconfig'
make defconfig
# 在初始配置基础上进行定制
make menuconfig
一定要按照以下列表启用/禁用/设定其中列出的内核特性,否则系统可能不能正常工作,甚至根本无法引导:
General setup --->
[ ] Compile the kernel with warnings as errors [WERROR]
CPU/Task time and stats accounting --->
[*] Pressure stall information tracking [PSI]
[ ] Require boot parameter to enable pressure stall information tracking
... [PSI_DEFAULT_DISABLED]
< > Enable kernel headers through /sys/kernel/kheaders.tar.xz [IKHEADERS]
[*] Control Group support ---> [CGROUPS]
[*] Memory controller [MEMCG]
[ ] Configure standard kernel features (expert users) ---> [EXPERT]
Processor type and features --->
[*] Build a relocatable kernel [RELOCATABLE]
[*] Randomize the address of the kernel image (KASLR) [RANDOMIZE_BASE]
General architecture-dependent options --->
[*] Stack Protector buffer overflow detection [STACKPROTECTOR]
[*] Strong Stack Protector [STACKPROTECTOR_STRONG]
Device Drivers --->
Generic Driver Options --->
[ ] Support for uevent helper [UEVENT_HELPER]
[*] Maintain a devtmpfs filesystem to mount at /dev [DEVTMPFS]
[*] Automount devtmpfs at /dev, after the kernel mounted the rootfs
... [DEVTMPFS_MOUNT]
Graphics support --->
< /*/M> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support) --->
... [DRM]
# If [DRM] is selected as * or M, this must be selected:
[ /*] Enable legacy fbdev support for your modesetting driver
... [DRM_FBDEV_EMULATION]
Console display driver support --->
# If [DRM] is selected as * or M, this must be selected:
[ /*] Framebuffer Console support [FRAMEBUFFER_CONSOLE]
在构建 64 位系统,还需要启用一些特性:
# 如果使用 menuconfig 进行配置,需要首先启用 CONFIG_PCI_MSI,然后启用 CONFIG_IRQ_REMAP,最后启用 CONFIG_X86_X2APIC,这是因为只有选定了一个选项的所有依赖项后,该选项才会出现。
Processor type and features --->
[*] Support x2apic [X86_X2APIC]
Device Drivers --->
[*] PCI support ---> [PCI]
[*] Message Signaled Interrupts (MSI and MSI-X) [PCI_MSI]
[*] IOMMU Hardware Support ---> [IOMMU_SUPPORT]
[*] Support for Interrupt Remapping [IRQ_REMAP]
由于使用 NVMe存储 设备,所以参考 gentoo linux wiki: NVMe 配置内核
Device Drivers --->
NVME Support --->
<*> NVM Express block device
<*> NVM Express block device
[*] NVMe multipath support
[*] NVMe hardware monitoring
< > NVM Express over Fabrics FC host driver
< > NVM Express over Fabrics TCP host driver
[ ] NVMe over Fabrics In-Band Authentication in host side
以下配置我没有找到
<M> NVMe Target support
[*] NVMe Target Passthrough support
<M> NVMe loopback device support
<M> NVMe over Fabrics FC target driver
< > NVMe over Fabrics FC Transport Loopback Test driver (NEW)
<M> NVMe over Fabrics TCP target support
由于我使用XFS:
File system --->
<*> XFS filesystem support
[ ] Support deprecated V4 (crc=0) format
[ ] Support deprecated case-insensitive ascii (ascii-ci=1) format
[*] XFS Quota Support
[*] XFS POSIX ACL Support
[*] XFS Realtime subvolume Support
[*] XFS online metadata check Support
[*] XFS online metadata check usage data collection (NEW)
[*] XFS online metadata repair Support
[ ] XFS Verbose Warnings
[ ] XFS Debugging support
编译和安装:
#编译内核映像和模块
make
#安装内核模块
make modules_install
# 复制编译好的内核
cp -iv arch/x86/boot/bzImage /boot/vmlinuz-6.10.5-lfs-12.2
# System.map 是内核符号文件,它将内核 API 的每个函数入口点和运行时数据结构映射到它们的地址。它被用于调查分析内核可能出现的问题。
cp -iv System.map /boot/System.map-6.10.5
# 内核配置文件 .config 由上述的 make menuconfig 步骤生成,包含编译好的内核的所有配置选项。最好能将它保留下来以供日后参考
cp -iv .config /boot/config-6.10.5
# 安装 Linux 内核文档
cp -r Documentation -T /usr/share/doc/linux-6.10.5
配置Linux内核模块加载顺序
多数情况下 Linux 内核模块可以自动加载,但有时需要指定加载顺序。负责加载内核模块的程序 modprobe 和 insmod 从 /etc/modprobe.d 下的配置文件中读取加载顺序,例如,如果 USB 驱动程序 (ehci_hcd、ohci_hcd 和 uhci_hcd) 被构建为模块,则必须按照先加载 echi_hcd,再加载 ohci_hcd 和 uhci_hcd 的正确顺序,才能避免引导时出现警告信息。
执行以下命令创建文件 /etc/modprobe.d/usb.conf
/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
设置GRUB
警告
由于我使用EFI引导,所以这段参考BLFS的 Using GRUB to Set Up the Boot Process with UEFI
内核UEFI支持配置
在内核配置中启用UEFI支持
Processor type and features --->
[*] EFI runtime service support [EFI]
[*] EFI stub support [EFI_STUB]
-*- Enable the block layer ---> [BLOCK]
Partition Types --->
[ /*] Advanced partition selection [PARTITION_ADVANCED]
[*] EFI GUID Partition support [EFI_PARTITION]
Device Drivers --->
Firmware Drivers --->
[*] Mark VGA/VBE/EFI FB as generic system framebuffer [SYSFB_SIMPLEFB]
Graphics support --->
<*> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support) --->
... [DRM]
[*] Enable legacy fbdev support for your modesetting driver
... [DRM_FBDEV_EMULATION]
<*> Simple framebuffer driver [DRM_SIMPLEDRM]
Console display driver support --->
[*] Framebuffer Console support [FRAMEBUFFER_CONSOLE]
File systems --->
DOS/FAT/EXFAT/NT Filesystems --->
<*/M> VFAT (Windows-95) fs support [VFAT_FS]
Pseudo filesystems --->
<*/M> EFI Variable filesystem [EFIVAR_FS]
-*- Native language support ---> [NLS]
<*/M> Codepage 437 (United States, Canada) [NLS_CODEPAGE_437]
<*/M> NLS ISO 8859-1 (Latin 1; Western European Languages) [NLS_ISO8859_1]
创建紧急救援启动磁盘
这段创建一个启动U盘的工作我没有做,如有需要参看原文
找到或创建EFI系统分区
EFI系统中,bootloader是安装在一个特殊的称为 EFI System Partition(ESP)
FAT32分区。通常已经有Linux安装或者Windows安装的系统,可能已经创建好了ESP分区。
(这步我没有做,因为我已经有一个ESP分区挂载到
/boot
)如果是首次构建系统,创建以下ESP分区(案例是/dev/sda
)
mount --mkdir -v -t vfat /dev/sda1 -o codepage=437,iocharset=iso8859-1 \
/boot/efi
(我没有做)对应配置
/etc/fstab
:
cat >> /etc/fstab << EOF
/dev/sda1 /boot/efi vfat codepage=437,iocharset=iso8859-1 0 1
EOF
在我的实践中,我的磁盘分区是在 /dev/nvme0n1
上划分的两个分区,分区1是 ESP 分区,已经在 LFS分区( mbp15_late_2013) 中完成过了。
GRUB和EFI的最小化启动配置
在基于 UEFI 的系统上,GRUB 通过将 EFI 应用程序(一种特殊的可执行文件)安装到 ESP 中来工作。EFI 固件将从记录在 EFI 变量中的引导条目以及 硬编码路径 EFI/BOOT/BOOTX64.EFI
中搜索 EFI 应用程序中的引导加载程序。
要在硬编码路径 EFI/BOOT/BOOTX64.EFI
中安装带有 EFI 应用程序的 GRUB,首先确保启动分区安装在 /boot
上,ESP
安装在 /boot/efi
上。
备注
注意,如果ESP分区挂载在 /boot/efi
目录,那么 grub-install
不需要任何参数。但是,我的 ESP 分区改在在 /boot
分区,直接执行 grub-install
会提示找不到 EFI 目录。这个问题在 Gentoo GRUB 已经有实践经验。
我在 Gentoo GRUB 有实践记录,所以这里参考执行行如下(需要指定安装路径):
# 如果ESP分区挂载在 /boot 上,则是非标,需要指定efi目录
grub-install --target=x86_64-efi --removable --efi-directory=/boot
# 如果ESP分区挂载在 /boot/efi 上,则是标准路径
grub-install --target=x86_64-efi --removable
备注
这段话非常重要,请仔细体会
从GRUB视角来看,内核文件的位置相对于它使用的分区:
如果使用独立的
/boot
分区(ESP分区挂载到/boot
上),那么 grub 和boot分区在一个磁盘分区起点(/boot
为起点),从grub角度看内核和它是并列的,所以此时内核位置是/vmlinuz-6.10.5-lfs-12.2
,也就是要去掉/boot
-- 请注意 MacBook Pro上运行Arch Linux 就是这种方式)如果没有使用独立的
/boot
分区,也就是ESP分区是挂载到/boot/efi
上,那么分区起点就是/
,此时从grub看分区访问内核的路径就是/boot/vmlinuz-6.10.5-lfs-12.2
。这种方式是发行版主要采用的方式,都是采用ESP
分区挂载为/boot/efi
,所以你在/boot/grub/grub.cfg
中看到的配置是/boot/vmlinuz-6.10.5-lfs-12.2
备注
为了确保主机磁盘增减时候GRUB访问磁盘分区引导依然正确,应该将 /dev/sda
这样的设备路径改为分区和文件系统的UUID:
set root=(hdx,y)
替换为search --set=root --fs-uuid <内核所在文件系统的 UUID>
(注意是 磁盘文件系统UUIDroot=/dev/sda2
替换为root=PARTUUID=<构建 LFS 使用的分区的 UUID>
(注意是 分区UUID )
上述 search --set=root ...
方法在主流发行版 Ubuntu Linux 上就是这么设置的,可以参考
挂载EFI变量文件系统(efivars)
备注
我在 Ubuntu Linux 系统上看到默认就是挂载 efivars
文件系统,但是没有配置 /etc/fstab
就能挂载,可能是在其他地方有配置。我这里按照LFS的文档来完成
在UEFI平台安装GRUB需要EFI变量文件系统(EFI Variable file sysem, efivarfs
)挂载。所以这里执行:
efivarifs
mountpoint /sys/firmware/efi/efivars || mount -v -t efivarfs efivarfs /sys/firmware/efi/efivars
这个信息似乎是因为我的Host主机 Ubuntu Linux 已经挂载了 efivarfs
/etc/fstab
中添加 efivarifs
配置cat >> /etc/fstab << EOF
efivarfs /sys/firmware/efi/efivars efivarfs defaults 0 0
EOF
设置配置
我这里的ESP分区挂载在 /boot
不是标准的方法,后续实践应该挂载为 /boot/efi
建议系统安装 efibootmgr
,这样就能够执行 efibootmgr | cut -f 1
检查EFI中启动配置
efibootmgr
内容BootCurrent: 000F
Timeout: 0 seconds
BootOrder: 0002,0008,000F,0009,000A,000B,000C,000D,0010,000E,0011,0015,0000,0001,0003,0004,0005,0006,0007,0012
Boot0000 Embedded UEFI Shell
Boot0001 Diagnose Error
Boot0002 System Utilities
Boot0003 Intelligent Provisioning
Boot0004 Boot Menu
Boot0005 Network Boot
Boot0006 Embedded Diagnostics
Boot0007 View Integrated Management Log
Boot0008* Generic USB Boot
Boot0009* Embedded SATA Port 1 HDD : INTEL SSDSC2KW512G8
Boot000A* Embedded SATA Port 2 HDD : ST9500420AS
Boot000B* Embedded SATA Port 3 HDD : HGST HTS725050A7E630
Boot000C* Embedded SATA Port 4 HDD : ST9500325AS
Boot000D* Embedded FlexibleLOM 1 Port 1 : HPE Ethernet 1Gb 4-port 366FLR Adapter - NIC (PXE IPv4)
Boot000E* Embedded FlexibleLOM 1 Port 1 : HPE Ethernet 1Gb 4-port 366FLR Adapter - NIC (PXE IPv6)
Boot000F* ubuntu
Boot0010* Embedded FlexibleLOM 1 Port 2 : HPE Ethernet 1Gb 4-port 366FLR Adapter - NIC (PXE IPv4)
Boot0011* Embedded FlexibleLOM 1 Port 2 : HPE Ethernet 1Gb 4-port 366FLR Adapter - NIC (PXE IPv6)
Boot0012* Slot 2 : NVM Express Controller - PHBT85100270016N -INTEL MEMPEK1J016GAL -D5E4D25C
Boot0013* Front USB 2 : SanDisk' Cruzer Fit
Boot0014* Slot 1 : NVM Express Controller - S676NF0R908144 -SAMSUNG MZVL21T0HCLR-00B00 -B9382500
Boot0015* Embedded SATA Port 5 HDD : SDLF1CRR-019T-1HA1
可以看到,我的系统启动优先级是 Boot0002 System Utilities
=> Boot0008* Generic USB Boot
=> Boot000F* ubuntu
...
也就是为何我现在系统能够进入Ubuntu,是因为它排在第三启动顺序
我现在的LFS系统安装在 Boot0012* Slot 2 : NVM Express Controller - PHBT85100270016N -INTEL MEMPEK1J016GAL -D5E4D25C
这里启动的第一顺序是 Boot0002 System Utilities
,在HP服务器的iLO管理界面,通过调整系统启动磁盘顺序,就是调整这个 System Utilities
启动顺序(不过在 efibootmagr
中看不到)
不过,最好还是通过 efibootmgr
在命令好解决,类似 Gentoo Linux 安装实践
备注
我实际是通过HP服务器的iLO启动顺序来管理的
创建GRUB配置
/boot/grub/grub.cfg
配置文件中 root=
配置部分需要根据实际情况调整,我这里采用了UUID指定磁盘分区2,这个UUID也就是 /etc/fstab
中的配置
/boot/grub/grub.cfg
配置文件cat > /boot/grub/grub.cfg << EOF
# Begin /boot/grub/grub.cfg
default=0
timeout=15
insmod part_gpt
insmod ext2
insmod efi_gop
insmod efi_uga
if loadfont /boot/grub/fonts/unicode.pf2; then
terminal_output gfxterm
fi
menuentry "GNU/Linux, Linux 6.10.5-lfs-12.2" {
search --set=root --fs-uuid 81368941-bd96-4539-bf8e-7215d532a872
linux /boot/vmlinuz-6.10.5-lfs-12.2 root=PARTUUID=cf8d6f20-92bf-4f81-982e-50bea63e6ca3 ro
}
menuentry "Ubuntu, Linux 5.15.0-126-generic" {
search --set=root --fs-uuid caa4193b-9222-49fe-a4b3-89f1cb417e6a
linux /boot/vmlinuz-5.15.0-126-generic root=UUID=caa4193b-9222-49fe-a4b3-89f1cb417e6a ro
initrd /boot/initrd.img-5.15.0-126-generic
}
menuentry "Firmware Setup" {
fwsetup
}
EOF
这里我添加了2行配置GRUB串口输出,参考 How does one set up a serial terminal and/or console in Red Hat Enterprise Linux?
异常排查
启动以后Grub菜单页面显示之后,一旦选择并回车进入选项,则提示:
error: file '/boot/vmlinuz-6.10.5-lfs-12.2' not found.
Press any key to continue...
但是没有进一步提示,我不确定是不是磁盘挂载问题
我尝试把 grub.cfg
配置项复制到同一台服务器的 ubuntu
磁盘的 grub.cfg
配置中,然后在 HPE ProLiant DL360 Gen9服务器 的 HP服务器iLO技术 WEB管理界面中调整启动磁盘顺序,将 ubuntu
磁盘调整到前面。
这次 ubuntu
磁盘启动的gurb有详细信息,显示出错误内容:
VFS: Cannot open root device "UUID=81368941-bd96-4539-bf8e-7215d532a872" or unknown-block(0,0): error -6
Please append a correct "root=" boot option: here are the available partitions:
103:00000 14065664 nvme0n1
(driver?)
103:00001 373760 nvme0n1p1 85af5570-6841-45d2-b749-bd0fab135a8a
103:00002 13689856 nvme0n1p2 cf8d6f20-92bf-4f81-982e-50bea63e6ca3
0800 1875374424 sda
driver: sd
0001 f99998720 sda1 ba7c6674-5d6e-4aa5-a2ed-cb0e265b73b7
0002 125000704 sda2 8c19863f-e149-45d9-b217-d3ca9c46862f
0810 500107608 sdb
...
这个问题在LFS文档中其实有说明,需要仔细阅读理解:
关键点是
set root
指定哪个磁盘文件系统来搜索内核,我最初照抄文档中set root=(hd0,2)
存在的问题是我的服务器有多块硬盘,启动以后存在LFS的磁盘并不一定会固定是额卑微hd0
,所以应该修订为search --set=root --fs-uuid <内核所在文件系统的 UUID>
另一个关键点是
ESP
分区是挂载为/boot
还是/boot/efi
,这决定了内核获取从磁盘分区开始计算到底要不要包含/boot
(见上文)我已经修订上文的配置文件
最终完成
最终成功后的服务器登陆后检查
-bash-5.2# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/root 14G 1.6G 12G 12% /
devtmpfs 189G 0 189G 0% /dev
tmpfs 189G 1.6M 189G 1% /run
tmpfs 189G 0 189G 0% /dev/shm
/dev/nvme0n1p1 365M 188K 365M 1% /boot/efi
/dev/sda2 117G 13G 98G 12% /sources
efivarfs 176K 87K 85K 51% /sys/firmware/efi/efivars
可以看到一个基础的Linux系统只需要 1.6G
磁盘就可以运行起来
-bash-5.2# cat /proc/meminfo
MemTotal: 396110968 kB
MemFree: 395551992 kB
MemAvailable: 393931812 kB
Buffers: 6364 kB
Cached: 44116 kB
SwapCached: 0 kB
Active: 30416 kB
Inactive: 22696 kB
Active(anon): 104 kB
Inactive(anon): 7216 kB
Active(file): 30312 kB
Inactive(file): 15480 kB
Unevictable: 3072 kB
Mlocked: 0 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 0 kB
Writeback: 0 kB
AnonPages: 5868 kB
Mapped: 11560 kB
Shmem: 4680 kB
KReclaimable: 19964 kB
Slab: 86756 kB
SReclaimable: 19964 kB
SUnreclaim: 66792 kB
KernelStack: 7648 kB
PageTables: 972 kB
SecPageTables: 2056 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 198055484 kB
Committed_AS: 14936 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 228548 kB
VmallocChunk: 0 kB
Percpu: 11904 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
Hugetlb: 0 kB
DirectMap4k: 31228 kB
DirectMap2M: 5079040 kB
DirectMap1G: 399507456 kB
Linux内存管理 需要分析