本文介紹如何為具有特定、已知和靜態硬體配置的系統創建精簡、最小的 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 的方式建立一個新的正常映像檔。 如果出現問題,您仍可以使用 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
指令會傳回每一行的第一個欄位(使用 {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 設備 -
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
文件。