mkinitcpio/最小 initramfs
本文展示了如何为具有特定、已知和静态硬件配置的系统创建精简的最小 initramfs 镜像。此过程从 Falconindy (Dave Reisner) 的 使用 mkinitcpio 优化启动 一文中详细阐述。
Udev 要求
创建您自己的 initramfs 镜像的一大优势是您可以消除 udev
。仅此 hook 就在 initramfs 镜像中占用了相当大的空间(使用 LZ4 和 LZOP 大约 700-800 KiB,使用其他算法则更少)。更大的尺寸不仅会导致更长的启动时间(更多数据需要解压缩),而且初始化 udev
本身也需要一些额外的时间。但是,有些东西需要 udev
。这包括解析 UUID、LABEL、PARTUUID 和 PARTLABEL 标识符(workaround hook without-udev)以及包含 root
分区的 LVM 和 mdadm 设备的组装。如果您不确定是否需要 udev
,请继续执行此页面上的说明,直到 #初始测试。如果删除 udev
后并非所有功能都正常工作,请重新启用该 hook 并重试。
此外,虽然大多数键盘(AT、PS/2、USB)不需要使用 udev
hook,但使用 Logitech Unified Receiver 的 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 的方式构建。如果出现问题,您可以依赖 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
是被 sourced 的,因此您可以像在 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
存储设备模块
sd_mod
用于所有 SCSI、SATA 和 PATA (IDE) 设备ahci
用于现代 AHCI 控制器上的 SATA 设备nvme
和nvme_core
用于 NVMe (M.2, PCI-E) 设备sata_*
用于 IDE 模式控制器上的 SATA 设备pata_*
用于 PATA (IDE) 设备ehci_pci
和usb_storage
用于 USB 存储设备virtio_blk
和virtio_pci
用于使用 VirtIO 进行存储的 QEMU/KVM 虚拟机
键盘模块
atkbd
用于 AT 和 PS/2 键盘,以及 QEMU/KVM 中的模拟键盘。hid_generic
、ohci_pci
和usbhid
用于普通 USB 键盘。hid_logitech_dj
、uhci_hcd
和usbhid
用于使用 Logitech Unified Receiver 的 Logitech USB 键盘(需要udev
hook)。
完成
一旦您尽可能地精简了您的 initramfs,请从您的 .preset
文件中删除(或注释掉)normal_*
行,并从 /boot
中删除 initramfs-linux*-normal.img
文件。