计算机启动过程
Linux 的完整启动过程,本质上是一个控制权不断移交的过程。
可以先记住最核心的一条主线:
计算机上电
↓
BIOS / UEFI 固件
↓
Bootloader(例如 GRUB)
↓
Linux Kernel
↓
initramfs 中的 /init
↓
挂载真正的 Root Filesystem
↓
switch_root
↓
真正根文件系统中的 PID 1
↓
systemd / SysV init / Upstart
↓
系统服务
↓
Shell / GUI
也就是说,整个启动过程实际上是在不断回答:
当前是谁控制 CPU?接下来又把控制权交给谁?
一、Linux Kernel 被加载之后做什么?
Bootloader 将 Linux Kernel 和 initramfs 加载到内存后,会把 CPU 控制权交给 Linux Kernel。
Kernel 开始执行自己的初始化过程。
主要包括:
1. 初始化 CPU 和内存管理
内核首先初始化自身运行所需要的基础环境,例如:
CPU
中断
物理内存管理
虚拟内存
页表
调度器
时钟
建立完整的内核运行环境。
2. 探测和初始化硬件
Linux 内核会识别能够发现的硬件设备,例如:
CPU
内存
PCI / PCIe
磁盘控制器
NVMe
USB
网卡
显卡
ACPI
设备树(ARM 系统常见)
但需要注意:
“发现硬件”和“加载驱动”并不是完全独立的两个固定步骤。
Linux 在初始化各个内核子系统和驱动时,会不断发现、匹配和初始化设备。
二、Linux 如何加载驱动?
Linux 驱动有两种主要存在方式。
1. Built-in Driver
直接编译进 Linux Kernel:
Kernel
├── ext4
├── NVMe
├── SATA
└── ...
这种驱动不需要额外加载 .ko 文件。
2. Loadable Kernel Module
驱动也可以编译成:
*.ko
即:
Kernel Object(内核模块)
通常位于:
/lib/modules/<kernel-version>/
现代发行版也经常实际位于:
/usr/lib/modules/<kernel-version>/
例如:
/usr/lib/modules/6.12.0/kernel/
问题是:
如果挂载根文件系统需要的 NVMe、RAID、LVM、文件系统等驱动本身就在根文件系统里,那么根文件系统还没有挂载时,内核怎么读取这些驱动?
因此需要:
initramfs
三、initramfs 是什么?
initramfs:
Initial RAM Filesystem
中文通常翻译为:
初始内存文件系统
它是 Linux 启动早期使用的一个临时根文件系统。
Bootloader 通常会同时加载:
Linux Kernel
+
initramfs
例如:
/boot/vmlinuz-xxx
/boot/initramfs-xxx.img
ARM64 系统则经常是:
/boot/Image
/boot/initramfs-linux.img
四、为什么需要 initramfs?
假设真正的 Linux 根文件系统位于:
/dev/nvme0n1p2
并且使用:
ext4
但是:
NVMe 驱动
ext4 驱动
LVM
RAID
LUKS
其中部分组件并没有直接编译进 Kernel。
那么就会产生一个启动悖论:
Kernel 想挂载 RootFS
↓
需要 NVMe / ext4 等驱动
↓
驱动文件在 RootFS
↓
但 RootFS 还没挂载
↓
无法读取驱动
initramfs 就是用来解决这个问题的。
它提前把启动阶段需要的:
驱动
工具
Shell
脚本
udev
文件系统工具
LVM 工具
RAID 工具
磁盘解密工具
等内容准备好。
五、initramfs 是什么时候创建的?
initramfs 通常是在:
安装操作系统
安装 / 升级内核
修改启动相关配置
时由用户空间工具生成。
生成工具会根据发行版的规则、配置以及系统环境,把启动所需要的模块和工具打包进去。
不同发行版常见工具例如:
RHEL / CentOS / Fedora → dracut
Debian / Ubuntu → initramfs-tools
Arch Linux → mkinitcpio
历史上的 CentOS / RHEL 5 常见:
mkinitrd
因此不能简单理解成:
“安装程序探测一次硬件,然后永久生成一个 ramdisk。”
更准确地说:
initramfs 是根据当前内核、系统配置、启动环境和所需模块构建出来的早期用户空间。
内核升级以后通常也会重新生成对应版本的 initramfs。
六、initrd、ramdisk 和 initramfs 的区别
这几个概念经常混用,但严格来说并不完全相同。
传统 initrd
initrd:
Initial RAM Disk
传统方式更接近:
在内存中创建一个块设备,并在上面使用文件系统。
现代 initramfs
initramfs:
Initial RAM Filesystem
通常是一个压缩的:
cpio archive
Kernel 将其解包到内存中的 rootfs。
所以现代 Linux 中更准确的说法是:
initramfs 是启动早期的临时根文件系统,而不是简单地“把一部分内存模拟成磁盘”。
另外:
Linux 使用 RAM 做 Page Cache / Buffer Cache 来加速磁盘访问,与 initramfs 是两个不同概念。
不要把:
Page Cache
RAM Disk
initrd
initramfs
混为一谈。
七、Linux Kernel 如何切换到真正的根文件系统?
Kernel 解包 initramfs 后,会运行其中的:
/init
注意:
initramfs 中的 /init
和稍后真正系统中的:
/sbin/init
不是同一个启动阶段的程序。
initramfs 中的 /init 会负责:
加载必要内核模块
↓
识别存储设备
↓
等待设备出现
↓
处理 RAID / LVM / LUKS 等
↓
找到真正的 RootFS
↓
挂载 RootFS
真正根文件系统通常会临时挂载到类似:
/sysroot
或某些实现中的:
/new_root
例如:
initramfs
│
├── bin
├── dev
├── proc
├── sys
├── init
└── sysroot
↓
真正的 Linux 根文件系统
然后通过:
switch_root
完成根文件系统切换。
逻辑上可以理解为:
原来的 /
↓
initramfs
/sysroot
↓
真正的 RootFS
执行:
switch_root
之后:
新的 /
↓
真正的 RootFS
随后释放不再需要的 initramfs 环境,并启动真正系统中的 PID 1。
八、启动用户空间的第一个进程
真正的 RootFS 准备完成之后,系统会启动用户空间的第一个进程:
PID = 1
传统上经常称为:
/sbin/init
现代 systemd Linux 中:
/sbin/init
通常实际上是指向:
/usr/lib/systemd/systemd
等 systemd 可执行文件的符号链接。
可以查看:
ps -p 1 -o pid,comm,args
或者:
readlink -f /sbin/init
PID 1 非常特殊。
它负责启动和管理整个用户空间中的大量系统服务。
因此可以理解:
Kernel
↓
启动 PID 1
↓
PID 1
├── 网络服务
├── SSH
├── 日志服务
├── cron
├── 登录服务
├── display manager
└── 其他系统服务
九、Linux 历史上的三种主要 init 系统
1. CentOS 5:SysV init
CentOS 5 主要使用:
SysV init
主要配置文件:
/etc/inittab
服务启动脚本通常位于:
/etc/init.d/
并通过不同运行级别对应的目录控制:
/etc/rc0.d/
/etc/rc1.d/
/etc/rc2.d/
/etc/rc3.d/
/etc/rc4.d/
/etc/rc5.d/
/etc/rc6.d/
RHEL/CentOS 中也常见:
/etc/rc.d/init.d/
/etc/rc.d/rc*.d/
十、CentOS 6:Upstart
CentOS 6 主要使用:
Upstart
Upstart 是一种事件驱动的 init 系统。
主要配置目录:
/etc/init/
配置文件通常为:
/etc/init/*.conf
例如:
/etc/init/tty.conf
/etc/init/serial.conf
需要纠正:
/etc/init.d/*.conf
不是 Upstart 的主要配置路径。
/etc/init.d/ 主要用于兼容传统 SysV init 服务脚本。
CentOS 6 在使用 Upstart 的同时保留了大量 SysV 兼容机制。
十一、CentOS 7:systemd
CentOS 7 开始使用:
systemd
systemd 的核心配置单位称为:
Unit
例如:
.service
.target
.socket
.mount
.timer
.path
.device
系统自带 Unit 文件主要位于:
/usr/lib/systemd/system/
管理员自己创建或覆盖的 Unit 通常位于:
/etc/systemd/system/
优先级通常是:
/etc/systemd/system/
↓
覆盖
↓
/usr/lib/systemd/system/
因此:
一般不建议直接修改
/usr/lib/systemd/system/中由软件包提供的 Unit 文件。
因为软件升级可能覆盖修改。
十二、BIOS + MBR 启动流程
下面讨论传统:
Legacy BIOS
+
MBR
启动模式。
整体流程:
Power On
↓
POST
↓
BIOS
↓
选择 Boot Device
↓
读取 MBR
↓
Bootloader
↓
GRUB
↓
Kernel + initramfs
↓
Kernel
↓
RootFS
↓
PID 1
十三、第一阶段:POST 加电自检
计算机通电后,CPU 从体系结构规定的复位入口开始执行固件代码。
BIOS/固件执行:
POST
Power-On Self-Test
即:
加电自检
主要完成:
CPU 初始化
内存检测
基础芯片组初始化
显卡初始化
键盘等基础设备检测
存储控制器检测
十四、BIOS 存在哪里?
这里需要纠正一个常见误区:
BIOS 并不是“从 CMOS 中读取出来运行”的。
BIOS 固件本身存储在主板上的:
ROM / EEPROM / Flash
现代主板一般使用 Flash 存储芯片。
传统 PC 中的 CMOS RAM 主要用于保存:
时间
日期
部分 BIOS 设置
启动顺序等配置
因此更准确的关系是:
Flash / ROM
↓
BIOS 固件
CMOS / NVRAM
↓
BIOS 配置信息
十五、BIOS 选择启动设备
BIOS 根据 Boot Sequence:
SSD
HDD
USB
CD/DVD
Network/PXE
选择启动设备。
然后读取传统磁盘的:
LBA 0
即磁盘第一个扇区。
传统扇区通常:
512 Bytes
十六、MBR 的结构
经典 MBR:
LBA 0
512 Bytes
布局:
Offset Size
0–445 446 Bytes Bootstrap Code
446–509 64 Bytes Partition Table
510–511 2 Bytes Boot Signature
最后两个字节:
55 AA
即:
0x55AA
因此:
┌─────────────────────────────┐
│ Boot Code 446 Bytes │
├─────────────────────────────┤
│ Partition Table 64 Bytes │
├─────────────────────────────┤
│ 0x55AA 2 Bytes │
└─────────────────────────────┘
=
512 Bytes
注意:
446 字节只是 MBR 中可以使用的启动代码区域,并不是完整的 GRUB。
空间太小,不可能放下完整 GRUB。
十七、GRUB 为什么分阶段加载?
传统 BIOS + MBR 环境下,GRUB 通常需要分阶段加载。
可以概念化理解成:
BIOS
↓
MBR 中的一小段 GRUB 代码
↓
GRUB Core Image
↓
/boot/grub2/ 中的模块和配置
↓
完整 GRUB 环境
历史资料中经常称:
Stage 1
Stage 1.5
Stage 2
GRUB2 的实际实现已经不完全使用这种传统命名,但这种方式仍然有助于理解。
十八、MBR Gap 是什么?
传统 MBR 分区磁盘中,MBR 后、第一个分区之前经常存在一段未分区空间。
历史系统可能是:
LBA 1 ~ LBA 62
大约:
31 KiB
因此老资料经常称其为:
MBR Gap
GRUB 可以利用其中一部分空间存放:
core.img
但是:
不能认为所有现代磁盘的 MBR Gap 都固定是“第 2~63 扇区、31KB”。
现代磁盘通常按照 1 MiB 对齐,第一个分区可能从:
LBA 2048
开始。
所以 MBR Gap 的大小取决于磁盘实际分区布局。
十九、GRUB 加载 Kernel
GRUB 完整运行以后读取自己的配置,例如常见:
/boot/grub2/grub.cfg
或者某些发行版:
/boot/grub/grub.cfg
其中包含类似:
linux /boot/vmlinuz-...
initrd /boot/initramfs-....img
GRUB 根据配置:
读取 Linux Kernel
+
读取 initramfs
↓
加载到内存
↓
传递 Kernel Command Line
↓
跳转到 Kernel 入口
此时:
GRUB 将 CPU 控制权交给 Linux Kernel。
二十、BIOS + MBR 完整启动链
因此可以总结:
① Power On
↓
② POST
↓
③ BIOS
↓
④ Boot Sequence
↓
⑤ 读取磁盘 LBA 0
↓
⑥ 执行 MBR Boot Code
↓
⑦ 加载 GRUB Core
↓
⑧ 加载完整 GRUB
↓
⑨ GRUB 读取 grub.cfg
↓
⑩ 加载 Kernel + initramfs
↓
⑪ Kernel 初始化
↓
⑫ 解包 initramfs
↓
⑬ 执行 initramfs /init
↓
⑭ 加载驱动、发现真正 RootFS
↓
⑮ 挂载真正 RootFS
↓
⑯ switch_root
↓
⑰ 启动 PID 1
↓
⑱ systemd / SysV init / Upstart
↓
⑲ 启动系统服务
↓
⑳ Shell / GUI
二十一、UEFI + GPT 启动流程
现代计算机更常见的是:
UEFI
+
GPT
它和 BIOS + MBR 最大的不同之一是:
UEFI 不需要依靠 MBR 中那 446 字节启动代码来加载操作系统。
UEFI 本身能够识别 GPT,并能够读取 EFI System Partition 中的 FAT 文件系统。
二十二、UEFI 固件
UEFI 固件通常存放在主板的:
SPI NOR Flash
中。
容量根据主板不同可能有:
8 MiB
16 MiB
32 MiB
...
因此不要把:
BIOS = 1MB
UEFI = 8~16MB
当成固定规范。
它们只是不同年代硬件上可能出现的典型容量。
二十三、UEFI 启动设备
计算机启动后:
Power On
↓
UEFI Firmware
↓
硬件初始化
↓
读取 UEFI NVRAM Boot Entries
↓
选择 Boot Entry
UEFI Boot Manager 可以根据 NVRAM 中保存的启动项找到:
EFI System Partition
简称:
ESP
二十四、GPT 磁盘基本结构
GPT 磁盘大致:
LBA 0
Protective MBR
LBA 1
Primary GPT Header
LBA 2 ~ ...
GPT Partition Entry Array
后面
实际分区数据
磁盘尾部
Backup GPT Partition Entry Array
最后一个 LBA
Backup GPT Header
注意:
“LBA 1~33 固定全部属于 GPT”并不是适用于所有 GPT 磁盘的绝对规则。
在典型的 512 字节逻辑扇区、128 个分区表项配置中,经常看到:
LBA 1 GPT Header
LBA 2–33 Partition Entry Array
但 GPT 表项数量、扇区大小等因素会影响实际占用空间。
二十五、Protective MBR
GPT 磁盘仍然保留:
LBA 0
称为:
Protective MBR
它主要是为了兼容旧式只认识 MBR 的工具,避免这些工具把 GPT 磁盘误认为“未分区磁盘”。
其中通常存在一个:
Partition Type = 0xEE
的保护分区项。
需要纠正:
UEFI 启动时通常不是先检查 0x55AA → 再检查 0xEE → 再由此寻找 GPT。
UEFI 固件本身能够理解 GPT。
Protective MBR 主要用于:
保护 GPT 磁盘免受旧 MBR 工具破坏。
二十六、GPT 如何识别?
GPT 的核心标识位于:
LBA 1
的 GPT Header。
其开头包含签名:
EFI PART
ASCII:
"EFI PART"
对应十六进制:
45 46 49 20 50 41 52 54
这才是识别 GPT Header 的关键标志之一。
GPT Header 中会记录:
Partition Entry Array 的位置
分区表项数量
每个分区表项大小
Backup GPT Header 位置
CRC 校验
磁盘 GUID
二十七、EFI System Partition(ESP)
GPT 分区表中通常存在:
EFI System Partition
简称:
ESP
ESP 通常使用 FAT 文件系统,常见为 FAT32。
里面存放 EFI 可执行程序:
*.efi
例如:
EFI/
├── Microsoft/
├── ubuntu/
├── fedora/
├── arch/
└── BOOT/
Linux GRUB 可能存在类似:
/EFI/fedora/shimx64.efi
/EFI/fedora/grubx64.efi
x86-64 默认/可移动介质启动路径常见:
/EFI/BOOT/BOOTX64.EFI
ARM64 则常见:
/EFI/BOOT/BOOTAA64.EFI
二十八、UEFI 如何加载 GRUB?
UEFI 本身可以:
识别 GPT
↓
访问 ESP
↓
读取 FAT 文件系统
↓
加载 *.efi
因此不需要:
MBR 446 Bytes
↓
Stage 1
↓
Stage 1.5
这种传统 BIOS 引导链。
正常情况下:
UEFI Boot Manager
↓
根据 NVRAM Boot Entry
↓
找到 ESP
↓
加载 grubx64.efi / shim / 其他 EFI Loader
如果使用默认 fallback 路径,则可能:
x86-64
/EFI/BOOT/BOOTX64.EFI
ARM64
/EFI/BOOT/BOOTAA64.EFI
二十九、UEFI + GRUB 后面的过程
一旦 GRUB EFI 程序运行:
UEFI
↓
GRUB EFI
↓
读取 grub.cfg
↓
找到 Kernel
↓
找到 initramfs
↓
加载到内存
↓
启动 Kernel
从这里开始:
BIOS + MBR 和 UEFI + GPT 的启动流程逐渐汇合。
后面基本都是:
Kernel
↓
initramfs
↓
RootFS
↓
PID 1
↓
systemd
三十、UEFI + GPT 完整启动链
可以总结为:
① Power On
↓
② UEFI Firmware
↓
③ POST / Hardware Init
↓
④ UEFI Boot Manager
↓
⑤ 读取 Boot Entry
↓
⑥ 找到 ESP
↓
⑦ 加载 EFI Bootloader
↓
⑧ GRUB EFI
↓
⑨ grub.cfg
↓
⑩ Kernel + initramfs
↓
⑪ Kernel 初始化
↓
⑫ 解包 initramfs
↓
⑬ 执行 /init
↓
⑭ 加载驱动
↓
⑮ 找到真正 RootFS
↓
⑯ 挂载 RootFS
↓
⑰ switch_root
↓
⑱ 启动 PID 1
↓
⑲ systemd
↓
⑳ Services
↓
Shell / GUI
三十一、BIOS + MBR 与 UEFI + GPT 对比
BIOS + MBR
BIOS
↓
MBR Boot Code
↓
GRUB Core
↓
GRUB
↓
Kernel
↓
initramfs
↓
RootFS
↓
PID 1
而:
UEFI + GPT
UEFI
↓
GPT / ESP
↓
*.efi
↓
GRUB
↓
Kernel
↓
initramfs
↓
RootFS
↓
PID 1
二者最主要的区别集中在:
计算机上电
↓
Kernel 被加载
之前。
Kernel 真正开始运行以后,两者的 Linux 启动流程基本汇合。
三十二、SysV init 的运行级别 Runlevel
传统 SysV init 使用:
Runlevel
控制系统启动模式。
RHEL/CentOS 传统定义大致为:
0 Halt / Poweroff
1 Single User Mode
2 Multi-user Mode
3 Full Multi-user Text Mode
4 Reserved / Undefined
5 Graphical Mode
6 Reboot
即:
0 → 关机
1 → 单用户 / 救援模式
2 → 多用户模式
RHEL/CentOS 历史定义中通常不启动 NFS
3 → 完整多用户文本模式
常用于服务器
4 → 保留 / 用户自定义
5 → 完整多用户 + 图形界面
6 → 重启
三十三、单用户模式需要注意
传统资料经常写:
Runlevel 1
=
直接进入 root
不需要密码
这是历史环境中的常见情况,但不能作为所有现代 Linux 的通用规则。
现代发行版是否要求 root 密码、是否进入 emergency shell、是否允许直接修改系统,取决于:
发行版
systemd 配置
PAM
root 密码状态
启动参数
安全策略
因此更准确的描述是:
Runlevel 1 代表单用户维护模式,主要用于系统维护和故障恢复;是否要求认证取决于具体系统配置。
三十四、查看 SysV 运行级别
可以使用:
runlevel
例如:
N 3
也可以:
who -r
查看运行级别相关信息。
三十五、systemd 不再使用传统 Runlevel 作为核心机制
CentOS 7 / RHEL 7 以后使用:
systemd target
代替传统 Runlevel。
常见对应关系:
SysV systemd
0 → poweroff.target
1 → rescue.target
2 → multi-user.target
3 → multi-user.target
4 → multi-user.target
5 → graphical.target
6 → reboot.target
三十六、查看 systemd 默认启动模式
执行:
systemctl get-default
可能得到:
multi-user.target
表示:
文本多用户模式
或者:
graphical.target
表示:
图形界面模式
三十七、修改默认启动模式
设置文本模式:
systemctl set-default multi-user.target
设置图形模式:
systemctl set-default graphical.target
实际上通常会修改:
/etc/systemd/system/default.target
这个符号链接。
查看:
ls -l /etc/systemd/system/default.target
三十八、临时切换 Target
例如进入文本多用户模式:
systemctl isolate multi-user.target
进入图形模式:
systemctl isolate graphical.target
进入 Rescue:
systemctl isolate rescue.target
三十九、救援模式和“基础驱动”不是一回事
需要纠正一个比较重要的概念:
进入 rescue.target / single-user mode,并不意味着 Linux 自动换成了一套“最基础的硬件驱动”。
Runlevel / Target 主要控制:
启动哪些用户空间服务。
例如:
graphical.target
↓
启动 Display Manager
启动图形环境
multi-user.target
↓
不启动完整 GUI
rescue.target
↓
只启动最基本的系统服务
但 Kernel 在更早阶段就已经初始化了大量硬件和驱动。
因此如果问题本身发生在:
GPU Kernel Driver
Kernel Module
initramfs
Kernel
阶段,仅仅切换到 rescue.target 不一定能够解决。
针对显卡问题,有时可能需要:
nomodeset
或者:
modprobe.blacklist=<module>
等内核启动参数。
四十、Linux 启动故障应该按阶段判断
理解启动流程以后,排错时不要简单地认为:
“黑屏 = 驱动冲突。”
应该先判断系统死在哪个阶段。
例如:
完全没有厂商 Logo
↓
Firmware / Hardware
能进 UEFI,但找不到启动项
↓
ESP / EFI Boot Entry
出现 GRUB Rescue
↓
GRUB / Partition / Filesystem
GRUB 正常,Kernel Panic
↓
Kernel / initramfs / Driver
出现:
Cannot mount root fs
↓
RootFS / Driver / initramfs
进入 emergency mode
↓
fstab / filesystem / systemd
出现登录终端,但没有 GUI
↓
Display Manager / GPU / Desktop
GUI 黑屏
↓
GPU / Wayland / Xorg / Desktop 等
这也是学习 Linux 启动过程最实际的意义:
知道系统在哪一层失败。
四十一、最终需要记住的完整启动模型
BIOS + MBR
Power
↓
POST
↓
BIOS
↓
Boot Device
↓
MBR
↓
GRUB Core
↓
GRUB
↓
Kernel + initramfs
↓
Kernel
↓
initramfs /init
↓
Driver / Storage / LVM / LUKS
↓
RootFS
↓
switch_root
↓
PID 1
↓
systemd
↓
Services
↓
Login / GUI
UEFI + GPT
Power
↓
UEFI
↓
Boot Manager
↓
GPT
↓
ESP
↓
*.efi
↓
GRUB
↓
Kernel + initramfs
↓
Kernel
↓
initramfs /init
↓
Driver / Storage / LVM / LUKS
↓
RootFS
↓
switch_root
↓
PID 1
↓
systemd
↓
Services
↓
Login / GUI
四十二、一句话总结
Linux 的启动过程,本质上就是:
固件找到 Bootloader → Bootloader 找到并加载 Linux Kernel 和 initramfs → Kernel 初始化硬件和内核子系统 → initramfs 准备并挂载真正的根文件系统 → switch_root → 启动 PID 1 → systemd 等 init 系统启动各种服务 → 最终进入 Shell 或图形桌面。
而 BIOS 与 UEFI 最大的区别主要发生在:
Power On
↓
Linux Kernel 被加载
这一阶段。
Kernel 开始运行以后,两条启动路线最终都会汇合为:
Kernel
↓
initramfs
↓
RootFS
↓
PID 1
↓
systemd
↓
Linux 用户空间
浙公网安备 33010602011771号