mkinitcpio/极简 initramfs
本文介绍如何为具有特定、已知和静态硬件配置的系统创建精简、最小的 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
文件。 以下示例将在 default
处配置最小的 initramfs 映像 ,and create a new normal
image that is built The 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
钩子不在 Arch Linux 默认的配置中,在 *_options
行的 -S
参数中包含无关的钩子不会导致错误。
找出需要的模块[编辑 | 编辑源代码]
找出机器需要的模块的最快方法是重启电脑,使用 fallback
映像并通过引导加载程序(boot loader)添加 break=postmount
内核参数。于是在根文件系统挂载好后便可进入命令行界面。
重启电脑后,通过以下命令来获取需要的模块:
lsmod | awk 'NF==3{print $1}'
awk
command returns only the first field, using {print $1}
, of every line with exactly 3 fields, enforced by NF==3
. Module dependencies include the 4th field to show which module pulled in the dependency, thus being filtered out due to that fourth field. Arch's mkinitcpio
takes care of dependencies for legitimate values included in the arrays MODULES=()
, FILES=()
, and 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 设备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
适用于使用罗技统一接收器的罗技 USB 键盘(需要 {ic|udev}} 钩子)。
收尾工作[编辑 | 编辑源代码]
将 initramfs 压缩到最小后,移除(或注释掉).preset
文件中的 normal_*
行,并移除 /boot
中的 initramfs-linux*-normal.img
文件。