1. 计算机启动概述:从按下电源键到操作系统启动的完整硬件与固件流程概览

计算机的启动过程是一个从硬件初始化到软件加载的精密协作流程。当用户按下电源键时,系统从完全断电状态开始,依次经历电源供给、固件自检、硬件枚举、引导加载程序执行,最终将控制权移交给操作系统内核。本章将拆解这一完整链条,为后续深入分析 Linux 内核启动奠定基础。

1.1 启动流程全景图

下图展示了从按下电源键到操作系统内核启动的完整硬件与固件流程。每个阶段都有明确的输入、输出和关键组件参与。

计算机启动完整流程全景图 计算机启动完整流程全景图 ① 电源上电 PWR_OK / 时钟稳定 ② CPU 复位 CS:IP = 0xF000:0xFFF0 ③ BIOS / UEFI POST → 硬件枚举 ④ 引导设备 MBR / GPT ⑤ Bootloader GRUB / syslinux ⑥ Linux 内核 start_kernel() ⑦ init 进程 systemd / init 关键说明 • 阶段①-③:硬件初始化 • 阶段④-⑤:引导加载 • 阶段⑥-⑦:操作系统启动 • 整个流程约 2-30 秒 时间分布参考 • POST:0.5-3 秒 • Bootloader:1-5 秒 • 内核初始化:0.5-3 秒 • init 启动:1-10 秒

1.2 启动阶段详细分解

计算机启动过程可以划分为七个核心阶段,每个阶段都有明确的硬件/软件组件参与和特定的输出结果。

阶段 名称 主要参与者 关键输出 典型耗时
① 电源上电 电源管理单元 (PMU)、时钟发生器 PWR_OK 信号、时钟稳定 100-500ms
② CPU 复位 CPU 内部逻辑、复位向量 CS:IP = 0xF000:0xFFF0 < 1ms
③ BIOS/UEFI 初始化 固件 ROM、CMOS、NVRAM POST 完成、硬件枚举表 0.5-3s
④ 引导设备选择 固件、引导顺序列表 MBR/GPT 扇区读取 0.1-1s
⑤ Bootloader 执行 GRUB/syslinux/LILO 内核映像加载到内存 1-5s
⑥ 内核初始化 Linux 内核 (start_kernel) 调度器、内存管理就绪 0.5-3s
⑦ init 进程启动 systemd / SysV init 用户态服务启动 1-10s

1.3 电源上电与硬件复位

按下电源键后,系统首先经历电源稳定和硬件复位两个关键子阶段。

1.3.1 电源上电时序

  • 电源键触发:电源键按下后,主板上的电源管理单元 (PMU) 检测到电平变化。
  • 电源就绪 (PWR_OK):ATX 电源输出稳定的 +3.3V、+5V、+12V 后,向主板发送 PWR_OK 信号。
  • 时钟发生器启动:主板上的时钟发生器 (Clock Generator) 开始输出稳定的系统时钟信号 (通常为 100MHz 基准时钟)。
  • 复位信号释放:芯片组在确认电源和时钟稳定后,释放 CPU 的 RESET# 引脚。
关键指标:ATX 电源规范要求 PWR_OK 信号必须在所有电源输出稳定后的 100-500ms 内发出。如果电源质量不佳,可能导致复位时序异常,造成启动失败。

1.3.2 CPU 复位状态

当 RESET# 引脚从低电平变为高电平时,CPU 进入复位状态。x86 架构 CPU 复位后的初始状态如下:

寄存器 复位值 说明
CS (代码段) 0xF000 基地址 = 0xFFFF0000 (实模式)
IP (指令指针) 0xFFF0 偏移量
EFLAGS 0x00000002 IF=0 (中断关闭)
CR0 0x60000010 PE=0 (实模式), EM=1
GDTR 0x00000000 全局描述符表基址清零

CPU 复位后,第一条指令从物理地址 0xFFFFFFF0 开始执行(对应 CS:IP = 0xF000:0xFFF0,在实模式下 CS 基址为 0xFFFF0000)。这个地址映射到固件 ROM 的最后 16 字节,包含一条跳转指令,指向 BIOS/UEFI 的入口代码。

架构差异:ARM 架构的复位向量通常位于 0x00000000 或 0xFFFF0000(取决于实现),且复位后 CPU 处于 SVC (Supervisor) 模式。RISC-V 架构的复位向量由硬件设计决定,通常位于内存映射的高地址区域。

1.4 BIOS 与 UEFI 固件阶段

固件阶段是硬件初始化的核心环节,负责将系统从原始硬件状态提升到可引导状态。现代系统主要使用 UEFI,但 BIOS (Legacy) 仍在大量嵌入式系统和旧硬件中存在。

1.4.1 BIOS 与 UEFI 对比

特性 BIOS (Legacy) UEFI
接口模式 16 位实模式 32/64 位保护模式
引导扇区 MBR (512 字节) GPT + ESP 分区
磁盘容量 最大 2.2TB 最大 9.4ZB
启动速度 较慢 (串行初始化) 较快 (并行初始化)
网络支持 PXE (扩展) 内置 HTTP/iSCSI
安全启动 不支持 Secure Boot
驱动模型 Option ROM UEFI 驱动

1.4.2 POST 执行流程

加电自检 (POST) 是固件阶段的核心任务,按以下顺序执行:

  1. CPU 测试:验证 CPU 内部寄存器和缓存。
  2. 芯片组初始化:配置内存控制器、PCIe 根复合体。
  3. 内存检测:检测并初始化 DRAM,建立内存映射表。
  4. 总线枚举:扫描 PCI/PCIe 总线,分配资源 (MMIO、IRQ)。
  5. 外设初始化:初始化存储控制器、USB 控制器、显示适配器。
  6. 引导设备枚举:列出可引导设备,按优先级排序。
常见故障点:内存检测失败通常表现为蜂鸣器长鸣(BIOS 特定编码);PCIe 设备初始化失败可能导致系统卡在 POST 阶段。UEFI 提供了详细的错误日志记录在 NVRAM 中,可通过 dmesg 或 UEFI Shell 查看。

1.5 引导设备选择与 MBR/GPT

固件完成 POST 后,根据配置的引导顺序列表依次尝试从各设备加载引导代码。

1.5.1 引导设备优先级

典型的引导顺序配置如下:

优先级 设备类型 典型接口 备注
1 USB 闪存盘 USB 2.0/3.0 系统安装/救援
2 NVMe SSD PCIe 3.0/4.0 现代主存储
3 SATA SSD/HDD SATA 3.0 传统主存储
4 网络 (PXE) 以太网 无盘工作站
5 光驱 SATA/USB 已逐渐淘汰

1.5.2 MBR 与 GPT 分区表结构

固件读取引导设备的第一个扇区(LBA 0),根据分区表类型决定后续加载方式。

项目 MBR (Legacy) GPT (UEFI)
扇区位置 LBA 0 (512 字节) LBA 0 (保护 MBR) + LBA 1 (GPT 头)
分区数量 最多 4 个主分区 最多 128 个分区 (默认)
分区大小 最大 2.2TB 最大 9.4ZB
冗余备份 无 GPT 头备份在磁盘末尾
校验机制 无 CRC32 校验
引导代码 MBR 前 446 字节 ESP 分区中的 .efi 文件
实战要点:在 UEFI 系统上,如果磁盘使用 MBR 分区表,固件会尝试以 CSM (Compatibility Support Module) 模式模拟 BIOS 引导。建议新系统统一使用 GPT + UEFI 组合,以获得更好的兼容性和安全性。

1.6 Bootloader 加载与执行

Bootloader 是固件与操作系统内核之间的桥梁。以 GRUB 2 为例,其加载过程分为多个阶段:

GRUB 2 引导加载流程 GRUB 2 引导加载流程 boot.img MBR 前 446 字节 core.img LBA 1-63 grub.cfg /boot/grub/ vmlinuz 内核映像 各阶段功能说明 ① boot.img:由固件加载到 0x7C00,仅 446 字节,负责定位并加载 core.img 的第一个扇区。 ② core.img:包含文件系统驱动,能够读取 /boot/grub/ 目录下的 grub.cfg 配置文件。 ③ grub.cfg:定义菜单项、内核参数、initrd 路径等,GRUB 根据配置加载 vmlinuz 和 initrd。 ④ vmlinuz:压缩后的 Linux 内核映像,GRUB 将其解压并跳转到入口点 (startup_32/64)。

1.7 内核启动入口

Bootloader 将控制权交给内核时,CPU 处于特定状态。x86 架构下,内核入口点根据引导协议约定:

  • 实模式入口:startup_32 (32 位) 或 startup_64 (64 位),位于内核映像的偏移 0x200 处。
  • 引导协议版本:Linux 内核支持多个引导协议版本 (v2.00 ~ v2.15),Bootloader 必须设置正确的 hdr 结构体。
  • 初始状态要求:Bootloader 需要提供 boot_params 结构体,包含内存映射、命令行参数、initrd 地址等信息。
// Linux 内核引导协议头结构 (arch/x86/include/uapi/asm/bootparam.h)
struct setup_header {
    __u8    setup_sects;        // 设置扇区数
    __u16   root_flags;         // 根文件系统标志
    __u32   syssize;            // 系统大小
    __u16   ram_size;           // 内存大小
    __u16   vid_mode;           // 视频模式
    __u16   root_dev;           // 根设备
    __u16   boot_flag;          // 0xAA55 引导标志
    __u16   jump;               // 跳转指令
    __u32   header;             // 头部签名 "HdrS"
    // ... 更多字段
    __u32   cmd_line_ptr;       // 命令行指针
    __u32   initrd_addr_max;    // initrd 最大地址
    __u32   kernel_alignment;   // 内核对齐要求
} __attribute__((packed));
调试技巧:在 GRUB 命令行中,可以使用 set debug=all 开启详细日志,观察内核加载过程中的内存地址和参数传递。内核启动后,通过 dmesg | grep -i "boot" 查看引导阶段的内核日志。

1.8 启动流程中的关键时序指标

以下表格汇总了启动流程中各阶段的关键时序指标,帮助工程师定位性能瓶颈:

阶段 理想时间 可接受时间 异常阈值 常见瓶颈
POST < 1s 1-3s > 5s 内存检测、PCIe 枚举
Bootloader < 1s 1-3s > 5s 磁盘 I/O、文件系统加载
内核解压 < 0.5s 0.5-2s > 3s CPU 性能、压缩算法
内核初始化 < 1s 1-3s > 5s 驱动加载、ACPI 解析
init 启动 < 2s 2-5s > 10s 服务依赖、网络等待
性能优化建议:如果系统启动时间超过 30 秒,建议使用 systemd-analyze blame 分析各服务耗时,或使用 bootchart 生成启动时序图。对于嵌入式系统,可以考虑使用 initramfs 裁剪和内核模块静态编译来缩短启动时间。

1.9 本章小结