跳转到内容
本页使用了标题或全文手工转换
来自 Arch Linux 中文维基

本文介绍如何为具有特定、已知和静态硬件配置的系统创建精简、最小的 initramfs。 Falconindy (Dave Reisner) 的 Optimizing Bootup With mkinitcpio 详细阐述了该过程。

Udev 要求

创建自己的 initramfs 映像的一大优点是可以移除 udev 钩子。这个钩子在 initramfs 中占了相当大一块空间(使用 LZ4 和 LZOP 压缩时约为 700-800 KiB,其他算法较小)。因此它不仅导致启动时加载耗时更长(需要解压更多的数据),而且初始化其自身时也要额外的时间。但是,仍有部分操作需要 udev,包括解析 UUID、LABEL、PARTUUID 和 PARTLABEL 标识符(workaround hook without-udev)以及包含 root 分区的 LVM 和 mdadm 设备。 若您不确定是否需要 udev,请继续按照本页上的说明操作,直到 #初步测试章节。如果在没有 udev 的时候出了问题,请重新启用此钩子,再试一次。

另请注意,虽然大部分键盘(AT,PS/2,USB)不需要 udev 钩子也能正常工作,但使用罗技统一接收器(Logitech Unified Receiver)的 USB 设备需要。此时,您可以在所有映像中包含 udev 或依赖 fallback 映像正常工作。

如果您确实需要 udev,最小化映像的努力可能就白费了。映像大小也许能减小约 600 KiB,但是启动时间不会有显著改变。在此情况继续下去,不失为一次学习机会。

编辑 .preset 文件

在 Falconidy 的教程中,他编辑 /etc/mkinitcpio.conf 并运行 mkinitcpio -g 来创建测试 initramfs 映像,使系统上已知正常启动的 initramfs 映像保持不变。 但是,如果您事后盲目运行 mkinitcpio -P,甚至 fallback 映像也会被删除。

准备自行创建 initramfs 的更安全方法是修改 /etc/mkinitcpio.d 中的 .preset 文件。以下的示例设定将以最小的 initramfs 映像取代default,并依照 The Arch Way 的方式建立一个新的正常映像文件。 如果出现问题,您仍可以使用 normalfallback 映像。 完成后,您可以从配置中删除 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_udevconsolefont钩子不在 Arch Linux 默认的配置中,在 *_options 行的 -S 参数中包含无关的钩子不会导致错误。

找出需要的模块

本文或本节需要翻译。要贡献翻译,请访问简体中文翻译团队

附注: 需要翻译(在 Talk:Mkinitcpio/极简 initramfs# 中讨论)

找出机器需要的模块的最快方法是重启电脑,使用 fallback 映像并通过引导加载程序(boot loader)添加 break=postmount 内核参数。于是在根文件系统挂载好后便可进入命令行界面。

重启电脑后,通过以下命令来获取需要的模块:

lsmod | awk 'NF==3{print $1}'
注意:awk 命令会返回每一行的第一个字段(使用 {print $1),但只限于那些刚好有三个字段的行,这是通过 NF==3 来强制筛选的。 模块依赖关系会包含第四个字段,用来显示是由哪个模块引入这个依赖,因此这些行会因为有第四个字段而被过滤掉。Arch 的 mkinitcpio 会处理那些正当包含在 MODULES=()FILES=()BINARIES=() 数组中的依赖项目。

保存已加载模块的清单,输入 exit 继续启动机器。

另一种方式是安装 hwdetect 来帮助确定所需的模块。虽然此软件包已停止维护,它仍可提供有价值的信息。另外,请参阅内核模块以开始使用本机工具。

初步编辑 mkinitcpio.conf

编辑 /etc/mkinitcpio.conf 修改 MODULES= 数组。值得注意 /etc/mkinitcpio.conf 作为脚本调用,可以使用 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 boot) 设备:
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 设备
  • nvmenvme_core 用于 NVMe(M.2、PCI-E)设备
  • sata_* 用于 IDE 模式控制器上的 SATA 设备
  • pata_* 用于 PATA(IDE)设备
  • ehci_pciusb_storage 用于 USB 存储设备
  • virtio_blkvirtio_pci 用于使用 VirtIO 进行存储的 QEMU/KVM 虚拟机

键盘模块

  • atkbd 用于 AT 和 PS/2 键盘,以及 QEMU/KVM 中的模拟键盘。
  • hid_genericohci_pciusbhid 用于普通 USB 键盘。
  • hid_logitech_djuhci_hcdusbhid 适用于使用罗技统一接收器的罗技 USB 键盘(需要 {ic|udev}} 钩子)。

收尾工作

将 initramfs 压缩到最小后,移除(或注释掉).preset 文件中的 normal_* 行,并移除 /boot 中的 initramfs-linux*-normal.img 文件。