Arch boot process (简体中文)
为了启动 Arch Linux,一个与 Linux 兼容的 启动引导器,比如 GRUB 或者 Syslinux 必须事先被安装到主引导记录或者 GUID 分区表。启动引导程序负责在初始化启动进程之前,加载好内核和 initial ramdisk。具体过程因 BIOS 和 UEFI 系统而异,细节在正文中给出。
Contents
固件种类
BIOS
所谓 BIOS 或 Basic Input-Output System, 就是开机时第一个被执行的程序,又名固件。一般来说它储存在主板上的一块闪存中,与硬盘彼此独立。
BIOS 被启动后,会按启动顺序加载磁盘的前 512 字节,即主引导记录,前 440 字节包含某个启动引导器,像 GRUB 、Syslinux 和 LILO 之类的第一启动阶段代码。因为空间太小了,后续的启动代码保存在磁盘上,最后启动引导器又通过「链式引导」,或是直接加载内核,以加载一个操作系统。
UEFI
UEFI 不仅能读取分区表,还能自动支持文件系统。所以它不像 BIOS,已经没有仅仅 440 字节可执行代码即 MBR 的限制了,它完全用不到 MBR。
UEFI 主流都支持 MBR 和 GPT 分区表。Apple-Intel Macs 上的 EFI 还支持 Apple 专用分区表。绝大部分 UEFI 固件支持软盘上的 FAT12,硬盘上的 FAT16、FAT32 文件系统,以及 CD/DVDs 的 IS09660 和 UDF。Intel Macs 的 EFI 还额外支持 HFS/HFS+ 文件系统。
不管第一块上有没有 MBR,UEFI 都不会执行它。相反,它依赖分区表上的一个特殊分区,叫 EFI 系统分区,里面有 UEFI 所要用到的一些文件。计算机供应商可以在 <EFI 系统分区>/EFI/<VENDOR NAME>/
文件夹里放官方指定的文件,还能用固件或它的 shell,即 UEFI shell,来启动引导程序。EFI 系统分区一般被格式化成 FAT32,或比较非主流的 FAT16。
系统初始化
BIOS
- 开机时加电自检。
- 加电自检后,BIOS 初始化一些必要的硬件以准备引导,比如硬盘和键盘等。
- BIOS 执行在「BIOS 硬盘顺序」中的第一块硬盘上的前 440 字节代码,即主引导记录。
- MBR 接管后,执行它之后的第二阶段代码,如果后者存在的话,它一般就是启动引导器。
- 第二阶段代码会读取它的支持文件和配置文件。
UEFI
- 系统开机 - 上电自检(Power On Self Test 或 POST)。
- UEFI 固件被加载,并由它初始化启动要用的硬件。
- 固件读取其引导管理器以确定从何处(比如,从哪个硬盘及分区)加载哪个 UEFI 应用。
- 固件按照引导管理器中的启动项目,加载UEFI 应用。
- 已启动的 UEFI 应用还可以启动其他应用(对应于 UEFI shell 或 rEFInd 之类的引导管理器的情况)或者启动内核及initramfs(对应于GRUB之类引导器的情况),这取决于 UEFI 应用的配置。
<EFI SYSTEM PARTITION>/EFI/boot/bootx64.efi
(对于 64 位的 x86 系统)UEFI 的多重引导
因为每个操作系统或者提供者都可以维护自己的 EFI 系统分区中的文件,同时不影响其他系统,所以 UEFI 的多重启动只是简单的运行不同的UEFI 程序,对应于特定操作系统的引导程序。这避免了依赖 chainloading 机制(通过一个启动引导程序加载另一个引导程序,来切换操作系统)。
启动加载器
启动加载器是 BIOS 或 UEFI 启动的第一个程序。它负责使用正确的 内核参数 加载内核, 并根据配置文件加载 初始化 RAM disk。对于 UEFI,内核本身可以由 UEFI 使用 EFI boot stub 直接启动,也可以使用单独的引导加载程序或引导管理器来在引导之前编辑内核参数。
功能比较
- 只需要启动加载器兼容内核和initramfs所处的位置(
/boot
)的文件系统兼容即可。 - 因为GPT是UEFI规范的一部分,所以所有的UEFI启动加载器都支持GPT磁盘。在BIOS上使用GPT磁盘是可行的,要么根据Hybrid MBR使用 "hybrid booting",要么使用新的 GPT-only 协议。但是这个协议可能在某些BIOS实现上出问题,参考 rodsbooks。
- 在文件系统支持中提到的“加密”是filesystem级别加密,和block级别加密没有任何关系。
Name | Firmware | Partition table | Multi-boot | File systems | Notes | ||||||
---|---|---|---|---|---|---|---|---|---|---|---|
BIOS | UEFI | MBR | GPT | Btrfs | ext4 | ReiserFS | VFAT | XFS | |||
EFISTUB | – | Yes | Yes | Yes | – | – | – | – | 仅 ESP | – | 内核会变成一个 EFI executable 来被 UEFI 固件或者其他启动加载器加载。 |
Clover | 模拟 UEFI | Yes | Yes | Yes | Yes1 | No | 不支持加密 | No | Yes | No | 修改版的 rEFIt,用来运行黑苹果。 |
GRUB | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | 在 BIOS/GPT 配置下需要一个 BIOS启动分区。 支持RAID, LUKS1 和 LVM (但是不支持thin provisioned volumes)。 |
rEFInd | No | Yes | Yes | Yes | Yes1 | 不支持加密和 zstd 压缩 | 不支持加密 | 不支持 tail-packing 功能 | Yes | No | 支持自动寻找内核和确定内核参数而不需要手动配置。 |
Syslinux | Yes | 有限支持 | Yes | Yes | 有限支持 | 不支持: 跨设备卷、压缩、加密 | 不支持加密 | No | Yes | 仅限MBR;不支持 sparse inodes | 不支持某些 文件系统 功能 [2] 启动加载器只能够访问它所处的文件系统。[3] |
systemd-boot | No | Yes | 仅限手动安装 | Yes | Yes1 | No | No | No | 仅 ESP | No | ESP以外的分区上的binaries它都启动不了. |
GRUB Legacy | Yes | No | Yes | No | Yes | No | No | Yes | Yes | 仅 v4 | 停止开发 in favor of GRUB. |
LILO | Yes | No | Yes | No | Yes | No | 不支持加密 | Yes | Yes | Yes | 停止开发 因为某些局限性 (e.g. with Btrfs, GPT, RAID). |
- 一种 启动管理器。它只能启动其他 EFI 应用程序,例如,使用
CONFIG_EFI_STUB=y
和 Windowsbootmgfw.efi
构建 Linux kernel images。
更多信息,参见 Wikipedia:Comparison of boot loaders。
内核
内核是操作系统的核心。它运行于一个叫「内核空间」的底层上,负责机器硬件和应用程序之间的交流。为了尽可能充分地压榨 CPU 性能,内核使用调度器,通过一定的优先级算法将 CPU 按照时间动态的分配给各个程序。让我们感觉就像所有程序都在同时使用 CPU 一样。
initramfs
在 boot loader[broken link: invalid section] 加载 kernel 和可用的 initramfs 文件,并执行 kernel 之后,kernel 将 initramfs(初始RAM文件系统)压缩包解压缩到(然后清空)rootfs(初始根文件系统,特别是ramfs或tmpfs)。首先提取的 initramfs 是在 kernel 构建过程中嵌入 kernel 二进制Update translation.的 initramfs,然后提取可用的外部 initramfs 文件。因此,外部 initramfs 中的文件会覆盖嵌入式 initramfs 中具有相同名称的文件。然后, kernel 执行 /init
(在rootfs中)作为第一个进程。early userspace开始。
Arch Linux 对内置的 initramfs 使用一个空的存档(在构建Linux时是默认的)。有关外部 initramfs 的更多信息和 Arch 特定的信息,请参见 mkinitcpio。
initramfs 之所以存在,是为了帮系统访问真正的根文件系统(参见 Arch filesystem hierarchy (简体中文))。也就是说,那些硬件 IDE, SCSI, SATA, USB/FW 所要求的 kernel 模块,如果并没有内置在 kernel 里,就会被 initramfs 负责加载。一旦通过 udev (简体中文) 之类的程序或脚本加载好模块,启动流程才会继续下去。所以,initramfs 只要有能够让系统访问真实根文件系统的模块就可以了,不用尽可能地包含一切模块。当然,其它真正有用的模块之后会在 init 流程中被 udev 加载好。
Init 流程
在「早期用户空间」的最终环节里,真正的根文件系统被挂载好后,就会替换掉原来的伪根文件系统。接着 /sbin/init
被执行,同样也替换掉原来的 /init
进程。Arch 御用的 init 就是 systemd (简体中文).
Getty
init 为每一个 虚拟终端 调用 getty,前者一般有六个,每个虚拟终端都会初始化 tty 并请求输入用户名和密码。当在某虚拟终端输入用户名和密码后,其 getty 会通过 /etc/passwd
检查是否正确,如果正确,就接着调用 login, 此外 getty 也可能会改启动一个显示管理器。
显示管理器
显示管理器, 可以配置为代替原来的 getty 登录命令行提示符。
为了在引导后自动初始化显示管理器,必须通过systemd手动启用服务单元。 有关启用和启动服务单元的更多信息,请参见systemd#使用单元。
Login
所谓的 login 程序会为用户启动一个设置了环境变量的「会话」,接着根据 /etc/passwd
的配置启动用户专用 shell。
在成功登录后,刚刚启动登录 shell 之前,login 程序显示 /etc/motd (message of the day) 。在这里,您可以显示服务条款,以提醒用户您的本地政策或您想告诉他们的任何内容。
Shell
一旦用户专用的 shell 启动了,它会在显示命令行提示符前,执行一个「有可执行性的配置文件」,比如 .bashrc. 如果用户有设定了 Start X at login, 原来那个「有可执行性的配置文件」会调用 startx or xinit.
GUI、 xinit 或者 wayland
xinit 也会调用用户的 .xinitrc 这个「有可执行性的配置文件」,后者一般用来启动一个 窗口管理器。如果用户退出了窗口管理器、xinit、 startx 和 shell login 就会先后中断,返回到 getty.