Arch 启动过程
为了启动 Arch Linux,必须设置一个支持 Linux 的引导加载器。引导加载器负责加载内核和 初始内存磁盘,然后启动引导过程。对于 BIOS 和 UEFI 系统,此过程差异很大。在本页或链接页面上提供了详细描述。
固件类型
固件是系统开启后执行的第一个程序。
UEFI
统一可扩展固件接口 支持读取分区表以及文件系统。UEFI 不会启动任何 来自主引导记录 (MBR) 的引导代码,无论它是否存在,而是依赖于 NVRAM 中的引导项进行启动。
UEFI 规范强制要求支持 FAT12、FAT16 和 FAT32 文件系统(参见 UEFI 规范 2.10 版本,第 13.3.1.1 节),但任何符合规范的供应商可以选择性地添加对其他文件系统的支持;例如,在某些 Apple 固件中支持 HFS+ 或 APFS。UEFI 实现也支持用于光盘的 ISO 9660。
UEFI 启动 EFI 应用程序,例如 引导加载器、引导管理器、UEFI shell 等。这些应用程序通常作为文件存储在 EFI 系统分区中。每个供应商可以将其文件存储在 EFI 系统分区下的 /EFI/vendor_name
目录中。可以通过向 NVRAM 添加引导项或从 UEFI shell 启动这些应用程序。
UEFI 规范支持使用其 兼容性支持模块 (CSM) 进行传统的 BIOS 启动。如果在 UEFI 中启用了 CSM,UEFI 将为所有驱动器生成 CSM 引导项。如果选择从 CSM 引导项启动,UEFI 的 CSM 将尝试从驱动器的 MBR 引导代码启动。
BIOS
BIOS 或基本输入输出系统在大多数情况下存储在主板本身的闪存中,并且独立于系统存储。最初为 IBM PC 创建,用于处理硬件初始化和引导过程,但自 2010 年以来已逐渐被 UEFI 取代,后者没有相同的技术限制。
系统初始化
系统开启后,执行 开机自检 (POST)。另请参阅 Hugo Landau 的 现代 CPU 的后台花絮。
UEFI
- POST 之后,UEFI 初始化启动所需的硬件(磁盘、键盘控制器等)。
- 固件读取 NVRAM 中的引导项,以确定要启动哪个 EFI 应用程序以及从哪里启动(例如,从哪个磁盘和分区)。
- 引导项可以只是一个磁盘。在这种情况下,固件在该磁盘上查找 EFI 系统分区,并尝试在回退引导路径
\EFI\BOOT\BOOTx64.EFI
中查找 EFI 应用程序(在具有 IA32(32 位)UEFI 的 系统上为BOOTIA32.EFI
)。这就是 UEFI 可启动可移动介质的工作方式。
- 引导项可以只是一个磁盘。在这种情况下,固件在该磁盘上查找 EFI 系统分区,并尝试在回退引导路径
- 固件启动 EFI 应用程序。
- 这可以是 引导加载器,也可以是 Arch 内核 本身,使用 EFI 引导存根。
- 它可能是其他一些 EFI 应用程序,例如 UEFI shell 或 引导管理器,如 systemd-boot 或 rEFInd。
如果启用了 安全启动,引导过程将通过签名验证 EFI 二进制文件的真实性。
多重启动
由于每个操作系统或供应商都可以在 EFI 系统分区 中维护自己的文件,而不会影响其他操作系统或供应商,因此使用 UEFI 进行多重启动只需启动与特定操作系统的引导加载器对应的不同 EFI 应用程序即可。这消除了依赖一个 引导加载器 的 链式加载 机制来加载另一个操作系统的需求。
另请参阅 与 Windows 双启动。
BIOS
- POST 之后,BIOS 初始化启动所需的硬件(磁盘、键盘控制器等)。
- BIOS 启动 BIOS 磁盘顺序中第一个磁盘的前 440 字节(主引导记录引导代码区域)。
- 引导加载器在 MBR 引导代码中的第一阶段随后从以下位置启动其第二阶段代码(如果有):
- 实际的 引导加载器 被启动。
- 然后,引导加载器通过链式加载或直接加载操作系统内核来加载操作系统。
引导加载器
引导加载器是由固件(BIOS 或 UEFI)启动的一段软件。它负责加载内核以及所需的 内核参数 和任何外部 initramfs 镜像。在 UEFI 的情况下,内核本身可以使用 EFI 引导存根 直接由 UEFI 启动。仍然可以使用单独的引导加载器或引导管理器,以便在启动前编辑内核参数。具有 32 位 IA32 UEFI 的系统需要支持混合模式启动的引导加载器。
/boot
目录中。这意味着引导加载器必须支持从块设备、堆叠块设备(LVM、RAID、dm-crypt、LUKS 等)到内核和 initramfs 镜像所在的文件系统的一切。由于几乎没有引导加载器支持此类堆叠块设备,并且由于文件系统可能会引入任何引导加载器可能尚不支持的新功能(例如 archlinux/packaging/packages/grub#7, FS#79857, FS#59047, FS#58137, FS#51879, FS#46856, FS#38750, FS#21733 和 fscrypt 加密目录),因此使用单独的 /boot 分区 和普遍支持的文件系统(如 FAT32)通常更可行。
功能比较
名称 | 固件 | 分区表 | 多重启动 | 文件系统 | 备注 | ||
---|---|---|---|---|---|---|---|
BIOS | UEFI | MBR | GPT | ||||
Clover | 是 | 是 | 否 | 是 | 是 | 可扩展2,5 | 可以在传统的 BIOS 系统上模拟 UEFI。 |
EFI 引导存根 | – | 是1 | 是 | 是 | – | 从固件继承2 | 内核是一个有效的 EFI 可执行文件,可以直接从 UEFI 或另一个 UEFI 引导加载器启动。 |
GRUB | 是 | 是3 | 是 | 是 | 是 | 内置 | 支持 RAID、LUKS(但不包括 Argon2 PBKDFs)和 LVM(但不包括精简配置卷)。有关特定于设置的限制,请参阅 GRUB。 |
Limine | 是 | 是3 | 是 | 是 | 是 | 有限 | |
rEFInd | 否 | 是 | 是 | 是 | 是4 | 可扩展2,5 | 支持自动检测内核和参数,无需显式配置,并支持快速启动 [2]。 |
Syslinux | 是 | 部分1 | 是 | 是 | 部分 | 有限 | 不支持某些文件系统功能。 只能访问它 安装到 的文件系统。 |
systemd-boot | 否 | 是3 | 手动 | 是 | 是4 | 可扩展2,5 | 只能从它安装到的 ESP 或同一磁盘上的扩展引导加载器分区 (XBOOTLDR 分区) 启动二进制文件。 自动检测放置在 esp/EFI/Linux/ 中的 统一内核镜像。 |
统一内核镜像 | – | 是3 | 是 | 是 | – | 从固件继承2 | systemd-stub(7),内核、initramfs 和内核命令行打包到 EFI 可执行文件中,以便直接从 UEFI 固件或另一个引导加载器加载。 |
GRUB Legacy | 是 | 否 | 是 | 否 | 是 | 有限 | 已停止开发,转而支持 GRUB。 |
LILO | 是 | 否 | 是 | 部分 | 是 | 有限 | 由于存在限制(例如,使用 Btrfs、GPT、RAID、加密),已停止开发。 |
- 虽然二进制文件可以为 安全启动 进行签名,但它不进行后续验证,从而破坏了信任链。
- 文件系统支持从固件继承。UEFI 规范强制要求支持 FAT12、FAT16 和 FAT32 文件系统[3],但供应商可以选择性地添加对其他文件系统的支持;例如,Apple Mac 中的固件支持 HFS+ 文件系统。如果固件提供在启动时加载 UEFI 驱动程序 的接口,则可以通过加载(独立获取的)文件系统驱动程序来添加对其他文件系统的支持。
- 支持混合模式启动。即,它可以在 32 位 IA32 UEFI 上启动 64 位 x86_64 Linux 内核。
- 引导管理器。它只能启动其他 EFI 应用程序,例如,使用
CONFIG_EFI_STUB=y
构建的 Linux 内核镜像和 Windows 启动管理器 (bootmgfw.efi
)。 - 支持加载 UEFI 文件系统驱动程序。
另请参阅 Wikipedia:引导加载器比较。
内核
引导加载器 启动包含 内核 的 vmlinux 镜像。
内核在底层(内核空间)运行,在机器硬件和程序之间进行交互。内核最初执行硬件枚举和初始化,然后继续进入用户空间。有关详细说明,请参阅 Wikipedia:内核 (操作系统) 和 Wikipedia:Linux 内核。
initramfs
initramfs(initial RAM file system,初始内存文件系统)镜像是一个 cpio 归档文件。Initramfs 镜像可以使用 mkinitcpio、dracut 或 booster 生成,并且是 Arch 设置早期用户空间的首选方法。
位于 /
的根文件系统最初是一个空的 rootfs,它是 tmpfs 或 ramfs 的一个特殊实例。这是 initramfs 镜像将被解压缩到的临时根文件系统。
initramfs 的目的是为早期用户空间提供必要的文件,以成功启动后期用户空间。它不需要包含人们可能想要使用的每个内核模块;它应该只包含根设备(如 NVMe、SATA、SAS、eMMC 或 USB(如果从外部驱动器启动))和加密所需的模块。大多数模块将在 init 过程中,在将根切换到根文件系统后,稍后由 udev 加载。
- 首先,内核将其内置的 initramfs 解压缩到临时根目录中。Arch Linux 的 官方支持的内核 对内置的 initramfs 使用空归档文件,这是构建 Linux 时的默认设置。
- 然后,内核按照 引导加载器 传递的命令行指定的顺序解压缩外部 initramfs 镜像,覆盖来自嵌入式 initramfs 或先前解压缩的任何文件。请注意,多个 initramfs 镜像可以组合在单个文件中,内核将按照它们在文件中的顺序处理它们。
- 如果第一个 initramfs 镜像未压缩,则在解压缩后,内核将分别在
/kernel/x86/microcode/
和/kernel/firmware/acpi/
中查找 CPU 微码 更新和 ACPI 表更新。 - 在处理完 CPU 微码和 ACPI 表更新后,内核将继续解压缩其余的 initramfs 镜像(如果有)。
- 如果第一个 initramfs 镜像未压缩,则在解压缩后,内核将分别在
此外,Linux 内核 固定 了它启动的原始根目录。如果未使用 initramfs,则真正的根文件系统可能最终无法在关机期间干净地卸载。
早期用户空间
早期用户空间阶段,也称为 initramfs 阶段,发生在 rootfs 中,rootfs 由 #initramfs 提供的文件组成。早期用户空间从内核执行 /init
二进制文件作为 PID 1 开始。
早期用户空间的功能是 可配置的,但其主要目的是引导系统到可以访问根文件系统的程度。这包括
- 设置根文件系统可能位于其上的存储堆栈,例如通过 dm-crypt、dm-verity、mdadm、LVM、systemd-repart 等。
- 通过 udev 将 持久块设备名称 解析为真实设备。
- systemd-modules-load(8) 加载内核模块,例如挂载真实根文件系统所需的任何块设备模块。
- 处理真实根文件系统的解密(如果适用)。
- 加载 DRM 模块,因为默认情况下为树内模块启用了 早期 KMS。
请注意,早期用户空间的功能不仅仅是设置根文件系统。有些任务只能在挂载根文件系统之前执行,例如 fsck 和从 休眠 恢复。
在早期用户空间的最后阶段,真实根目录被挂载到 /sysroot/
(在使用基于 systemd 的 initramfs 的情况下)或 /new_root/
(在使用基于 busybox 的 initramfs 的情况下),然后在使用基于 systemd 的 initramfs 时使用 systemctl switch-root
切换到该目录,或者在使用基于 busybox 的 initramfs 时使用 switch_root(8) 切换到该目录。后期用户空间通过执行来自真实根文件系统的 init 程序开始。
后期用户空间
后期用户空间的启动由 init 进程执行。Arch 官方使用基于单元和服务概念构建的 systemd,但此处描述的功能在很大程度上与其他 init 系统重叠。
getty
init 进程为每个虚拟终端(通常为六个)调用一次 getty。getty 初始化每个终端并保护它免受未经授权的访问。当提供用户名和密码时,getty 会根据 /etc/passwd
和 /etc/shadow
检查它们,然后调用 login(1)。
登录
login 程序通过设置环境变量并根据 /etc/passwd
启动用户的 shell 来开始用户的会话。login 程序在成功登录后,在执行登录 shell 之前,显示 /etc/motd (message of the day,每日消息) 的内容。这是显示您的服务条款以提醒用户您的本地策略或您希望告知他们的任何内容的好地方。
Shell
一旦用户的 shell 启动,它通常会运行一个运行时配置文件,例如 bashrc,然后再向用户显示提示符。如果帐户配置为 在登录时启动 X,则运行时配置文件将调用 startx 或 xinit。跳转到 #图形会话 (Xorg) 查看结尾。
显示管理器
此外,可以将 init 配置为在特定的虚拟终端上启动 显示管理器 而不是 getty。这需要手动启用其 systemd 服务文件。然后,显示管理器启动图形会话。
图形会话 (Xorg)
xinit 运行用户的 xinitrc 运行时配置文件,该文件通常启动 窗口管理器 或 桌面环境。当用户完成并退出时,xinit、startx、shell 和 login 将按顺序终止,返回到 getty 或显示管理器。