1. 启动流程概述:BIOS/UEFI 启动阶段、Bootloader 加载、内核初始化、根文件系统挂载
大家好,我是老李。做Linux系统工程师这么多年,每次有新人问我系统启动到底是怎么回事,我总会说:你先把启动流程搞明白,后面所有的问题都能迎刃而解。今天咱们就来聊聊这个最基础、也最关键的话题。
启动流程,说白了就是一台机器从按下电源键到出现登录提示符的全过程。我把它拆成四个阶段来讲:BIOS/UEFI、Bootloader、内核初始化、根文件系统挂载。嗯,咱们一个一个来。
1.1 BIOS/UEFI 启动阶段
机器通电后,CPU首先执行的是固件代码。这个固件,要么是传统的BIOS,要么是现代的UEFI。
BIOS(Basic Input/Output System),老古董了。它做的事情很简单:
- 自检(POST):检查内存、CPU、硬盘等硬件是否正常
- 读取MBR:从启动设备的主引导记录(第0扇区)读取512字节的引导代码
- 跳转到Bootloader:把控制权交给MBR里的代码
UEFI(Unified Extensible Firmware Interface),这是后来替代BIOS的。它更灵活,也更安全。
- 支持GPT分区表(BIOS只能用MBR)
- 可以直接读取FAT32分区上的EFI应用程序
- 支持安全启动(Secure Boot),防止恶意代码注入
我个人习惯:新机器一律用UEFI+GPT。为什么?因为MBR分区表最大只支持2TB磁盘,而且只能有4个主分区。你想想看,现在随便一块SSD都4TB起步了,用MBR不是给自己找麻烦吗?
避坑指南:我曾经遇到过一台服务器,BIOS里明明设置了从U盘启动,但死活进不去。查了半天,原来是U盘格式化成NTFS了,而BIOS只认FAT32。嗯,细节决定成败。
1.2 Bootloader 加载
BIOS/UEFI把控制权交给Bootloader后,真正的重头戏就开始了。Linux下最常见的Bootloader是GRUB2(GRand Unified Bootloader version 2)。
GRUB2做的事情:
- 加载自身:从磁盘读取GRUB的核心模块到内存
- 读取配置文件:解析
/boot/grub/grub.cfg,显示启动菜单 - 加载内核:根据用户选择,把vmlinuz内核文件和initramfs加载到内存
- 传递参数:把启动参数(如
root=/dev/sda1)传给内核 - 跳转到内核:把控制权交给内核的入口点
这里有个关键点:GRUB2需要能读取文件系统。它支持ext4、xfs、btrfs等常见文件系统,但如果你用了LVM或RAID,就得额外加载对应的模块。
注意:我曾经见过有人把 /boot 分区放在LVM上,结果GRUB2死活找不到内核。因为GRUB2的LVM支持是有限的,不是所有LVM配置都能识别。我的建议是:/boot 分区单独分出来,用ext4,不要用LVM。
1.3 内核初始化
内核被加载到内存后,开始执行初始化。这个过程大致分几步:
| 阶段 | 说明 |
|---|---|
| 解压缩内核 | vmlinuz是压缩过的,内核先把自己解压到内存 |
| 初始化CPU | 设置页表、中断描述符表、启动多核处理器 |
| 初始化内存管理 | 建立伙伴系统、slab分配器等 |
| 初始化设备驱动 | 扫描PCI总线、加载驱动、初始化存储控制器 |
| 挂载initramfs | 把initramfs作为临时根文件系统挂载 |
你可能会问:为什么需要initramfs? 因为真正的根文件系统可能在RAID上、在LVM上、或者需要网络才能访问。内核本身没有这些驱动,所以需要一个临时的根文件系统来加载必要的模块。
initramfs本质上是一个压缩的cpio归档文件,里面包含了:
- 必要的内核模块(如磁盘驱动、文件系统驱动)
- udev设备管理器
- 启动脚本(通常是
/init)
我记得有一次,客户说服务器启动到一半卡住了。我远程一看,内核已经加载完了,但就是挂不上根文件系统。查了日志才发现,initramfs里缺少了NVMe驱动。因为客户新换了一块NVMe SSD,但initramfs还是旧的。重新生成一下initramfs就搞定了。
1.4 根文件系统挂载
这是启动流程的最后一步,也是最容易出问题的一步。
initramfs里的启动脚本会做这些事情:
- 加载必要的内核模块:比如磁盘驱动、文件系统驱动
- 发现根设备:根据内核参数
root=找到根文件系统所在的设备 - 检查文件系统:如果
fsck需要,会检查根文件系统的完整性 - 挂载根文件系统:把真正的根文件系统挂载到
/sysroot - 切换到根文件系统:通过
pivot_root或switch_root切换到真正的根 - 启动init进程:执行
/sbin/init或/lib/systemd/systemd
这里有个细节:根文件系统的挂载参数。你可以在内核参数里指定,比如:
root=/dev/sda1 rootfstype=ext4 rootflags=noatime,data=ordered
或者用UUID来指定,这样更稳定:
root=UUID=1234-5678-90ab-cdef
我的建议:永远用UUID来指定根设备。因为设备名(如 /dev/sda)可能会变,但UUID是唯一的。我曾经遇到过一台机器,插了个U盘后,原来的 /dev/sda 变成了 /dev/sdb,结果系统启动不了了。用UUID就没这个问题。
1.5 常见问题与排查思路
启动阶段出问题,通常表现在这几个地方:
- BIOS/UEFI阶段:黑屏、报错、找不到启动设备。先检查启动顺序、磁盘连接、固件设置
- Bootloader阶段:GRUB菜单不出现、报错"file not found"。检查
/boot分区、GRUB配置 - 内核初始化阶段:内核崩溃(Kernel Panic)、驱动加载失败。检查内核参数、initramfs
- 根文件系统挂载阶段:挂载失败、进入紧急模式。检查
root=参数、文件系统完整性
排查工具:
- GRUB命令行:按
c进入,可以手动加载内核和initramfs - 内核日志:启动时按
Esc或F12查看详细输出 - 紧急模式:如果根文件系统挂载失败,系统会进入紧急模式,可以手动修复
最后提醒一句:修改启动配置前,一定要备份。我见过太多人改了 /etc/default/grub 后忘了运行 update-grub,结果下次启动直接黑屏。嗯,备份是底线。
好了,启动流程的四个阶段就讲到这里。下一章咱们会深入Bootloader的配置和调优,到时候再聊。