mkinitcpio/最小 initramfs
本文展示了如何为一个具有特定、已知和静态硬件配置的系统创建一个精简的、最小的 initramfs。此过程从 Falconindy (Dave Reisner) 的 使用 mkinitcpio 优化启动 一文中详细阐述。
Udev 要求
创建您自己的 initramfs 镜像的主要优势是可以消除 udev
。仅此 hook 就占用了 initramfs 镜像相当大的大小(使用 LZ4 和 LZOP 约为 700-800 KiB,使用其他算法则更少)。更大的尺寸不仅会导致更长的启动时间(更多数据需要解压缩),而且初始化 udev
本身也需要额外的时间。然而,有些东西需要 udev
。这包括解析 UUID、LABEL、PARTUUID 和 PARTLABEL 标识符(不使用 udev 的 workaround hook)以及包含 root
分区的 LVM 和 mdadm 设备的组装。如果您不确定是否需要 udev
,请继续按照此页面上的说明操作,直到 #初始测试。如果未启用 udev
时并非所有功能都正常工作,请重新启用 hook 并重试。
此外,虽然大多数键盘(AT、PS/2、USB)不需要使用 udev
hook,但使用 Logitech 优联接收器的 Logitech USB 设备则需要。此时,您可以选择在所有镜像中包含 udev
,或者依赖于包含 udev
的 fallback
镜像。
如果您需要 udev
,那么您的最小化努力很可能将是徒劳的。您可能仍然能够将镜像大小缩小约 600 KiB,但启动时间不会得到显着改善。在这种情况下继续下去仍然可能是一次有价值的学习经历。
编辑 .preset 文件
在 Falconidy 的教程中,他编辑了 /etc/mkinitcpio.conf
并运行 mkinitcpio -g
来创建测试 initramfs 镜像,使系统上已知的良好 initramfs 镜像保持不变。但是,如果您之后盲目运行 mkinitcpio -P
,即使是 fallback
镜像也会被精简。
一种更安全的方式来准备自己手动创建 initramfs 文件,是修改 /etc/mkinitcpio.d
中的 .preset
文件。以下示例配置将用最小的 initramfs 镜像取代 default
,并创建一个新的 normal
镜像,该镜像以 Arch Way 构建。如果出现问题,您可以依赖 normal
或 fallback
镜像。完成后,您可以从配置中删除 normal_*
行并删除 initramfs-linux*-normal.img
文件。
... PRESETS=('default' 'normal' 'fallback') ... default_options="-S udev,block,mdadm_udev,filesystems,keyboard,fsck,consolefont" ... #normal_config="/etc/mkinitcpio.conf" normal_image="/boot/initramfs-linux-normal.img" #normal_options="" ...
mdadm_udev
和 consolefont
hooks 不存在于默认的 Arch 配置中。在 *_options
行的 -S
参数中包含无关的 hooks 不会导致错误。查找需要的模块
找出您需要哪些模块的最快方法是使用 fallback
initramfs 镜像重启系统,并在启动加载程序的内核参数中添加 break=postmount
,以便在根文件系统挂载后进入命令行。
系统重启后,运行以下命令以查看您需要的模块
lsmod | awk 'NF==3{print $1}'
awk
命令仅返回每行正好有 3 个字段的第一字段,使用 {print $1}
,由 NF==3
强制执行。模块依赖项包括第 4 个字段以显示哪个模块引入了依赖项,因此由于第 4 个字段而被过滤掉。Arch 的 mkinitcpio
会处理数组 MODULES=()
、FILES=()
和 BINARIES=()
中包含的合法值的依赖项。写下已加载的模块,然后键入 exit
以继续启动。
或者,安装 软件包 hwdetect 以帮助确定必要的模块。虽然已不再维护,但它可以提供有价值的信息。另请参阅 内核模块 以开始使用原生工具。
mkinitcpio.conf 的初始编辑
编辑 /etc/mkinitcpio.conf
并修改 MODULES=
数组。值得注意的是,/etc/mkinitcpio.conf
是被 sourcing 的,因此您可以像在 bash 脚本中一样构建 MODULES 数组。
MODULES=() # filesystems MODULES+=() # storage MODULES+=() # keyboard MODULES+=() # miscellaneous
将所有模块添加到最后一个 miscellaneous
行。当您整理模块时,可以将它们放在适当的行中。
您还需要二进制文件来对 root
设备以及 /etc/fstab
中已设置为执行检查的任何其他挂载点执行文件系统检查。
- 对于 ext[2|3|4] 设备
BINARIES=(fsck fsck.ext[2|3|4] e2fsck)
- 对于 vfat (UEFI 启动) 分区
BINARIES=(fsck fsck.vfat dosfsck)
- 对于 btrfs 单磁盘设备
BINARIES=(fsck fsck.btrfs btrfsck)
- 对于 btrfs 多磁盘设备
BINARIES=(fsck fsck.btrfs btrfs btrfsck)
- 对于 xfs 设备
BINARIES=(fsck fsck.xfs xfs_repair)
- 这些示例中的第三个选项是可选的,但排除它们将阻止您修复损坏的文件系统,从而需要从另一个 initramfs 启动。
- 鼓励用户添加与其他文件系统相关的条目。
初始测试
编辑 /etc/mkinitcpio.conf
并运行 mkinitcpio -P
以重建所有 initramfs 镜像。然后重启。
如果您不需要 udev
,您的首次启动应该会成功。如果某些功能不起作用(例如,Arch 找不到您的根分区或键盘无法工作),那么您将需要返回并从 default_options
行的 -S
参数中删除 udev
,然后重试。如果您需要 udev
,请记住,您不会看到启动时间的显着改善,继续进行下去只对学习经验有好处。
模块分类
现在您已经拥有了已知的良好可启动 initramfs,是时候进一步精简 initramfs 了。正常的方法是一次删除几个模块,重建 initramfs 镜像,然后重启以查看一切是否仍然正常。如果您发现一切都不正常,请使用 fallback
initramfs 镜像重启,并重新添加已删除的模块,直到一切再次正常。重复此过程,直到只剩下您需要的模块。由于这可能是一个乏味的过程,因此提供以下列表是为了让人们在消除过程中抢先一步。
文件系统模块
root
设备以及 /etc/fstab
中将在启动时检查其文件系统的任何其他设备的文件系统模块。ext[2,3,4]
xfs
jfs
reiserfs
存储设备模块
- 所有 SCSI、SATA 和 PATA (IDE) 设备的
sd_mod
- 现代 AHCI 控制器上 SATA 设备的
ahci
- NVMe (M.2, PCI-E) 设备的
nvme
和nvme_core
- IDE 模式控制器上 SATA 设备的
sata_*
- PATA (IDE) 设备的
pata_*
- USB 存储设备的
ehci_pci
和usb_storage
- 使用 VirtIO 进行存储的 QEMU/KVM VM 的
virtio_blk
和virtio_pci
键盘模块
- AT 和 PS/2 键盘以及 QEMU/KVM 中模拟键盘的
atkbd
。 - 普通 USB 键盘的
hid_generic
、ohci_pci
和usbhid
。 - 使用 Logitech 优联接收器的 Logitech USB 键盘的
hid_logitech_dj
、uhci_hcd
和usbhid
(需要udev
hook)。
完成
一旦您尽可能精简了 initramfs,请从 .preset
文件中删除(或注释掉)normal_*
行,并从 /boot
中删除 initramfs-linux*-normal.img
文件。