这篇文章介绍了 linux 系统下从启动电源到用户看到 shell 的总体流程
四个阶段总览
1 | 阶段 1:固件阶段 |
阶段 1:固件阶段
目标:让机器从上电状态进入 bootloader。
1 | CPU 通电 / 复位 |
这一阶段的核心:
1 | 固件负责找到 bootloader。 |
这一阶段主要有两条路线:
1 | 传统路线:BIOS + MBR |
1. BIOS + MBR
BIOS 是什么?
BIOS 全称:
1 | Basic Input/Output System |
它是主板上的固件程序。CPU 上电后会先执行 BIOS。
BIOS 主要负责:
1 | 硬件自检 |
MBR 是什么?
MBR 全称:
1 | Master Boot Record |
它位于启动磁盘的第一个逻辑扇区,也就是:
1 | LBA 0 |
MBR 通常是 512 字节:
1 | MBR / 512 bytes |
MBR 里面有一小段启动代码,但空间很小,所以它通常只负责加载后续 bootloader。
BIOS 和 MBR 怎么加载 bootloader?
1 | BIOS |
核心理解:
1 | BIOS 不认识 Linux / Windows; |
2. UEFI + GPT
UEFI 是什么?
UEFI 全称:
1 | Unified Extensible Firmware Interface |
它是 BIOS 的现代替代方案。
UEFI 不再只会读取磁盘第一个扇区,而是能根据启动项去读取指定的 .efi 启动文件。
UEFI 主要负责:
1 | 硬件自检 |
GPT 是什么?
GPT 全称:
1 | GUID Partition Table |
它是现代磁盘分区表,用来替代 MBR 分区表。
GPT 的作用是描述磁盘分区:
1 | 有哪些分区 |
GPT 自己不负责执行代码,它只是磁盘的“分区地图”。
ESP 是什么?
ESP 全称:
1 | EFI System Partition |
它是 EFI 系统分区,通常是 FAT32 文件系统。
里面放 .efi 启动文件,例如:
1 | /EFI/ubuntu/grubx64.efi |
UEFI 和 GPT 怎么加载 bootloader?
1 | UEFI |
核心理解:
1 | UEFI 不再执行磁盘第一个扇区的启动代码; |
3. BIOS + MBR 和 UEFI + GPT 对比
| 对比项 | BIOS + MBR | UEFI + GPT |
|---|---|---|
| 启动入口 | 磁盘第一个扇区 | EFI 分区里的 .efi 文件 |
| 分区表 | MBR | GPT |
| bootloader 位置 | MBR 代码 + 后续阶段 | ESP 中的 .efi 文件 |
| 固件能力 | 比较原始 | 更现代 |
| 文件系统能力 | 基本不依赖文件路径 | 能读取 ESP 文件系统 |
| 多系统启动 | 容易争抢 MBR | 各系统可放自己的 .efi 文件 |
| 大磁盘支持 | 较弱 | 较好 |
| 安全能力 | 较弱 | 可支持 Secure Boot |
| 典型时代 | 传统 PC | 现代 PC |
阶段 2:Bootloader 阶段
目标:让 bootloader 找到并启动内核。
1 | bootloader 开始执行 |
这一阶段的核心:
1 | bootloader 负责找到 kernel,并把控制权交给 kernel。 |
这一阶段可以结合 GRUB 来理解,它是一种常见的 bootloader,Linux 系统中非常常见。
1. GRUB 是什么?
GRUB (GRand Unified Bootloader) 是固件和内核之间的启动程序。
它的位置在:
1 | BIOS / UEFI |
可以把 GRUB 理解成:
1 | GRUB = 一个能读配置、能读文件系统、能加载内核的智能 bootloader |
2. GRUB 从哪里来?
GRUB 不是硬件自带的,而是在安装系统或安装 bootloader 时写入磁盘的。
在 BIOS + MBR 模式下:
1 | BIOS |
在 UEFI + GPT 模式下:
1 | UEFI |
3. GRUB 读取什么配置?
GRUB 会读取自己的配置文件,常见是:
1 | /boot/grub/grub.cfg |
配置中会描述:
1 | 有哪些启动项 |
一个简化示例:
1 | menuentry "Linux" { |
其中:
1 | linux /boot/vmlinuz-linux ... |
表示加载 Linux 内核文件。
1 | initrd /boot/initramfs-linux.img |
表示加载 initramfs。
1 | root=UUID=xxxx rw quiet |
表示传给 kernel 的启动参数。
4. kernel 和 initramfs 分别是什么?
kernel 是操作系统内核本体,GRUB 负责把它加载到内存,并跳到它的入口。
initramfs 是一个早期临时根文件系统,它通常由 bootloader 和 kernel 一起加载。
可以简单理解为:
1 | kernel 是内核本体; |
5. GRUB 怎么启动 kernel?
GRUB 的核心流程如下:
1 | GRUB 开始执行 |
示意图:
1 | GRUB |
从这一刻开始:
1 | GRUB 退出主线,kernel 接管机器。 |
阶段 3:Kernel 阶段
目标:让内核接管机器,并启动第一个用户态进程。
1 | kernel 接管 CPU |
这一阶段的核心:
1 | kernel 负责建立内核世界,并启动 PID 1。 |
1. kernel 为什么要初始化?
bootloader 已经把 kernel 加载到内存,并跳转到 kernel 入口,但是此时很多核心能力还没有建立:
1 | 没有完整的内存管理 |
所以 kernel 进入后,第一件事是:
1 | 先把自己运行所需的基础设施搭起来。 |
2. kernel 初始化的主要工作
kernel 初始化的目标是:
1 | 让内核具备管理硬件、运行程序、提供系统服务的能力。 |
主要包括:
1 | kernel 初始化 |
这些初始化工作共同服务于一个目标:
1 | 让用户态程序能够安全地运行,并通过系统调用使用系统资源。 |
3. 为什么要挂载根文件系统?
kernel 要启动第一个用户态进程,但是用户态进程本质上是一个文件,例如:
1 | /sbin/init |
这些文件都存放在文件系统里。
因此 kernel 必须先挂载根文件系统:
1 | 某个磁盘分区 |
4. kernel 怎么接力给 init / systemd?
根文件系统挂载完成后,kernel 会尝试启动第一个用户态进程。
这个进程通常叫 init ,现代 Linux 里经常实际是 systemd:
在 wsl 上 init 是指向 systemd 的符号链接:
1 | lrwxrwxrwx 1 root root 22 Mar 14 00:48 /sbin/init -> ../lib/systemd/systemd* |
它的特殊之处是:
1 | 它是第一个用户态进程,PID = 1。 |
流程大致是:
1 | kernel 挂载根文件系统 / |
从这一刻开始:
1 | kernel 不再继续主动启动所有用户服务; |
阶段 4:用户态初始化阶段
目标:让用户态系统跑起来,并提供登录入口。
1 | init / systemd 作为 PID 1 开始执行 |
这一阶段的核心:
1 | PID 1 负责展开用户态世界,并让用户能够登录和使用系统。 |
总结:
1 | 固件找到 bootloader; |