1. Linux 启动流程概览:BIOS/UEFI → Bootloader → Kernel → init → systemd
Linux 系统的启动是一个多阶段、高度结构化的过程,从按下电源键到用户获得完整的交互式 shell 环境,经历了固件初始化、引导加载、内核解压、根文件系统挂载以及系统服务启动等关键步骤。理解这一流程是掌握内核参数解析与 systemd 调试的基础。
1.1 启动阶段总览
整个启动流程可划分为五个核心阶段,每个阶段都有明确的职责与输出产物:
| 阶段 | 执行主体 | 主要任务 | 输出/产物 |
|---|---|---|---|
| 1. 固件阶段 | BIOS / UEFI | 硬件自检(POST)、枚举启动设备、加载引导程序 | 启动设备选择、Bootloader 入口地址 |
| 2. 引导加载阶段 | GRUB2 / systemd-boot | 加载内核映像与 initramfs,传递内核参数 | 内核 vmlinuz + initramfs 到内存 |
| 3. 内核初始化阶段 | Linux Kernel | 解压内核、初始化子系统、挂载根文件系统 | 用户空间 PID 1 进程(init) |
| 4. 早期用户空间 | initramfs / init | 加载必要驱动、检测硬件、挂载真实根文件系统 | 切换到真实根文件系统 |
| 5. 系统服务阶段 | systemd (PID 1) | 并行启动系统服务、管理单元依赖、提供用户界面 | 多用户目标 / 图形界面 |
关键概念: 内核参数(kernel command-line parameters)主要在阶段 2 由 Bootloader 传递给内核,并在阶段 3 和阶段 4 被解析。systemd 在阶段 5 也会读取部分内核参数来调整自身行为(如
systemd.unit=、systemd.log_level=)。
1.2 启动流程 SVG 架构图
下图展示了从固件到 systemd 的完整启动链路,包含各阶段之间的数据流与控制流:
1.3 各阶段详细说明
1.3.1 固件阶段:BIOS 与 UEFI
- BIOS(Legacy):读取主引导记录(MBR,位于磁盘第一个扇区),执行 16 位实模式代码,加载 Bootloader 的第一阶段。
- UEFI(现代):读取 EFI 系统分区(ESP)中的引导管理器(如
grubx64.efi),支持安全启动(Secure Boot)和更丰富的启动配置。 - 关键差异:UEFI 支持 GPT 分区表、更大的磁盘容量、更快的启动速度,且不再依赖 MBR 的 512 字节限制。
调试提示: 如果系统无法启动,首先检查固件设置中的启动顺序。UEFI 系统可使用
efibootmgr 命令查看当前启动条目。
1.3.2 引导加载阶段:Bootloader
Bootloader 负责将内核映像(vmlinuz)和初始 RAM 磁盘(initramfs)加载到内存,并传递内核参数。以 GRUB2 为例,其工作流程如下:
- 第一阶段(boot.img):从 MBR 或 GPT 的 BIOS 启动分区加载,定位第二阶段。
- 第二阶段(core.img):加载文件系统驱动,读取
/boot/grub/grub.cfg配置文件。 - 菜单显示:呈现内核选择菜单,等待用户选择或超时自动启动。
- 加载内核与 initramfs:将 vmlinuz 和 initramfs 放入内存,设置内核命令行参数。
- 跳转到内核入口:执行
start_kernel(),控制权移交给内核。
# GRUB2 配置文件示例 (/boot/grub/grub.cfg)
menuentry 'Linux' {
linux /vmlinuz-6.1.0 root=/dev/sda2 ro quiet splash
initrd /initramfs-6.1.0.img
}
1.3.3 内核初始化阶段
内核获得控制权后,执行以下关键步骤:
- 解压内核:自解压代码将压缩的内核映像解压到内存中。
- 架构初始化:设置页表、中断描述符表(IDT)、内存管理单元(MMU)。
- 子系统初始化:按顺序初始化调度器、内存管理、VFS、网络协议栈等核心子系统。
- 挂载 initramfs:将 initramfs 作为临时根文件系统挂载,执行其中的
/init脚本。
注意: 内核参数中的
root= 指定真实根设备,但内核在挂载 initramfs 之前不会直接使用它。initramfs 负责加载存储控制器驱动,然后挂载真实根。
1.3.4 早期用户空间:initramfs
initramfs 是一个小型根文件系统,包含必要的内核模块、设备驱动和启动脚本。其典型工作流程:
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1 | 执行 /init |
通常是 shell 脚本或 BusyBox 二进制 |
| 2 | 加载内核模块 | 如存储控制器、文件系统驱动 |
| 3 | 检测硬件 | 创建设备节点,运行 udev |
| 4 | 挂载真实根文件系统 | 根据 root= 参数挂载 |
| 5 | 切换到真实根 | 执行 switch_root 或 pivot_root |
1.3.5 系统服务阶段:systemd
当 initramfs 完成切换后,真实根文件系统中的 systemd 作为 PID 1 启动。systemd 的初始化流程:
- 读取内核参数:解析
systemd.unit=、systemd.log_target=等参数。 - 加载默认目标:根据
default.target符号链接确定启动目标(如 multi-user.target 或 graphical.target)。 - 并行启动服务:基于单元依赖图,并行激活 socket、service、mount 等单元。
- 达到目标状态:所有依赖单元启动完成后,系统进入可用状态。
# 查看当前默认启动目标
systemctl get-default
# 临时切换到救援模式(通过内核参数)
# 在 GRUB 菜单编辑内核命令行,添加:
systemd.unit=rescue.target
1.4 启动流程中的关键内核参数
以下参数在启动流程的不同阶段被解析,对调试至关重要:
| 参数 | 解析阶段 | 作用 |
|---|---|---|
root= |
Kernel / initramfs | 指定真实根文件系统设备 |
ro / rw |
Kernel | 以只读或读写方式挂载根文件系统 |
quiet |
Kernel / systemd | 减少内核日志输出 |
systemd.unit= |
systemd | 覆盖默认启动目标 |
systemd.log_level= |
systemd | 设置 systemd 日志级别(debug/info/err) |
init= |
Kernel | 指定 PID 1 程序(覆盖 systemd) |
调试技巧: 在 GRUB 菜单按
e 键编辑启动项,删除 quiet 并添加 systemd.log_level=debug,可以获取详细的启动日志,帮助定位服务启动失败的原因。
1.5 启动流程总结
Linux 启动流程是一个精心设计的接力过程:
- 固件 负责硬件初始化和 Bootloader 加载。
- Bootloader 负责内核加载和参数传递。
- 内核 负责硬件抽象和核心子系统初始化。
- initramfs 负责驱动加载和真实根挂载。
- systemd 负责服务管理和用户空间初始化。