4、启动流程详解:BIOS/UEFI阶段、Bootloader阶段(GRUB)、内核初始化阶段、init进程启动
系统启动,说白了就是一台机器从按下电源键到出现登录界面的全过程。很多人觉得这步很简单,不就是开机嘛。但我在生产环境里排查过不下百次启动故障,每次都能发现新坑。今天咱们就把这四步拆开揉碎了讲清楚。
4.1 BIOS/UEFI阶段:硬件自检与引导选择
按下电源键的那一刻,CPU 首先执行的是固化在主板 ROM 里的代码。这就是 BIOS 或 UEFI 的起点。
BIOS(Basic Input/Output System) 是老传统了。它做三件事:
- POST(Power-On Self-Test):检查内存、CPU、显卡等关键硬件。如果听到滴滴声,别慌,那是它在告诉你哪里出了问题。
- 初始化硬件:给各个设备分配中断和 I/O 地址。
- 加载引导扇区:按照设定的启动顺序(硬盘、U盘、光驱),去读取第一个扇区(MBR)。
UEFI(Unified Extensible Firmware Interface) 是 BIOS 的现代替代品。我个人的习惯是,新服务器一律用 UEFI。为什么?
- 支持 GPT 分区表,突破 2TB 磁盘限制。
- 启动更快,因为它可以并行初始化设备。
- 有图形界面,操作更友好。
- 支持安全启动(Secure Boot),防止恶意软件劫持引导过程。
关键区别:BIOS 读取 MBR(主引导记录),UEFI 读取 ESP(EFI 系统分区)里的 .efi 文件。你想想看,MBR 只有 512 字节,能做的事很有限。而 ESP 分区可以放多个引导管理器,灵活多了。
我的经验:有一次客户服务器启动卡在 POST 阶段,排查了半天,结果是内存条松了。嗯,有时候最基础的问题反而最容易被忽略。建议你在 BIOS/UEFI 界面里先跑一遍硬件诊断工具。
4.2 Bootloader阶段(GRUB):引导加载器的工作
BIOS/UEFI 把控制权交给 Bootloader。在 Linux 世界里,GRUB(GRand Unified Bootloader)是绝对的主角。
GRUB 分两个阶段:
第一阶段(Stage 1):存储在 MBR 或 GPT 的引导扇区里。它很小,唯一任务就是加载 Stage 1.5 或直接加载 Stage 2。
第二阶段(Stage 2):这才是重头戏。它位于 /boot/grub 目录下。GRUB 会:
- 读取配置文件
/boot/grub/grub.cfg。 - 显示启动菜单,让你选择内核或进入恢复模式。
- 加载选定的内核镜像(vmlinuz)和 initramfs(初始内存文件系统)。
- 把控制权交给内核。
这里有个常见的坑。我曾经遇到过 GRUB 配置文件损坏,导致系统无法启动。解决办法是使用 Live CD 进入救援模式,重新安装 GRUB。
注意:修改 GRUB 配置后,一定要运行 update-grub 或 grub-mkconfig -o /boot/grub/grub.cfg。我见过有人手动编辑 grub.cfg,结果语法错误,启动直接黑屏。
来看一个典型的 GRUB 配置片段:
menuentry 'Ubuntu' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-xxxx' {
recordfail
load_video
gfxmode $linux_gfx_mode
insmod gzio
insmod part_gpt
insmod ext2
set root='hd0,gpt2'
linux /vmlinuz-5.15.0-86-generic root=/dev/sda2 ro quiet splash
initrd /initrd.img-5.15.0-86-generic
}
看到没?linux 行指定了内核路径和根分区,initrd 行指定了 initramfs。这两个文件缺一不可。
4.3 内核初始化阶段:从引导到内核启动
GRUB 把内核加载到内存后,内核就开始干活了。这个过程我把它分成三步:
第一步:解压与架构初始化
内核镜像通常是压缩的。它先自解压,然后设置页表、中断描述符表、初始化 CPU 的各个模式。说白了,就是给 CPU 铺好路,让它能跑起来。
第二步:设备驱动初始化
内核会扫描所有硬件设备,加载对应的驱动程序。这里有个顺序问题:
- 先初始化 PCI 总线,枚举所有 PCI 设备。
- 然后初始化存储控制器(如 SATA、NVMe)。
- 接着初始化网络设备、USB 控制器等。
我遇到过一个问题:新加的 NVMe 硬盘在启动时没被识别。排查后发现是内核版本太老,不支持该型号的 NVMe 控制器。升级内核后解决。
第三步:挂载根文件系统
内核需要找到根分区(/),才能继续加载用户空间的程序。但问题来了——根分区可能位于一个需要驱动才能访问的磁盘上(比如 LVM、RAID、加密分区)。
这就是 initramfs 的作用。它是一个微型根文件系统,包含了必要的驱动和工具。内核先挂载 initramfs,运行里面的 init 脚本,加载真正的根分区驱动,然后切换到真正的根文件系统。
核心流程:内核 → 挂载 initramfs → 加载驱动 → 挂载真实根分区 → 执行 /sbin/init
4.4 init进程启动:用户空间的第一个进程
内核初始化完成后,会启动用户空间的第一个进程——init。它的 PID 永远是 1。
传统上,Linux 使用 SysV init。它通过 /etc/inittab 定义运行级别,然后按顺序启动服务。但这种方式是串行的,启动慢。
现代 Linux 发行版大多改用 systemd。systemd 是并行启动的,能大幅缩短启动时间。我个人的习惯是,新部署的系统一律用 systemd。
systemd 的启动流程:
- 执行
/sbin/init(实际是 systemd 的符号链接)。 - 读取
/etc/systemd/system/default.target,确定默认启动目标(如 multi-user.target 或 graphical.target)。 - 并行启动所有依赖的服务单元(.service 文件)。
- 启动 getty 服务,显示登录提示符。
来看一个 systemd 服务单元的例子:
[Unit]
Description=My Custom Service
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/myapp
Restart=on-failure
[Install]
WantedBy=multi-user.target
这个服务会在网络就绪后启动,如果崩溃会自动重启。嗯,这里要注意 After 和 Wants 的区别:After 只控制顺序,不控制依赖。
避坑指南:我曾经写过一个服务,ExecStart 路径写错了,结果 systemd 一直报启动失败。排查了半天才发现是路径少了个斜杠。建议你写完服务单元后,用 systemd-analyze verify 检查语法。
最后,用一张表格总结这四个阶段:
| 阶段 | 主要任务 | 关键文件/组件 | 常见问题 |
|---|---|---|---|
| BIOS/UEFI | 硬件自检、选择启动设备 | MBR / ESP分区 | 硬件故障、启动顺序错误 |
| Bootloader | 加载内核和 initramfs | GRUB、grub.cfg | 配置文件损坏、内核缺失 |
| 内核初始化 | 设备驱动、挂载根文件系统 | vmlinuz、initramfs | 驱动不兼容、根分区无法挂载 |
| init进程启动 | 启动用户空间服务 | systemd、/sbin/init | 服务依赖错误、配置语法错误 |
启动流程看似复杂,但拆开来看,每一步都有明确的职责。你想想看,从按下电源键到出现登录提示符,中间经历了硬件检测、引导加载、内核启动、服务初始化四个环节。任何一个环节出问题,系统就起不来。所以,排查启动故障时,先定位是哪个阶段出了问题,再对症下药。