3. 固件与引导加载程序

在 Linux 启动性能优化中,固件与引导加载程序阶段常被忽视,但它决定了内核被加载前的全部耗时。传统 BIOS 与 UEFI 在初始化方式、磁盘寻址、驱动模型上存在本质差异;GRUB2 作为主流引导器,其配置项、模块加载、菜单渲染和超时策略都会直接影响启动时间。本节从启动链路出发,先厘清 BIOS 与 UEFI 的差异,再给出 GRUB2 配置优化与菜单精简的可落地方法。

一、核心原理:BIOS 与 UEFI 的启动差异

BIOS 采用 16 位实模式运行,通过 INT 13h 中断读取磁盘,受限于 MBR 分区表和 2TB 寻址能力。其启动流程为:加电自检(POST)→ 初始化硬件 → 读取 MBR → 执行引导代码 → 加载 GRUB 第一阶段。BIOS 阶段通常需要枚举 IDE/AHCI、USB、网卡等设备,耗时随外设数量增加而上升。

UEFI 则以 32/64 位保护模式运行,使用 分区表和 EFI 系统分区(ESP),支持从 FAT32 分区直接加载 .efi 可执行文件。UEFI 固件内置驱动模型,可并行初始化设备,并支持快速启动(Fast Boot)跳过部分自检。其启动流程为:SEC → PEI → DXE → BDS → 加载 grubx64.efi。相比 BIOS,UEFI 省去了实模式切换和中断调用,通常可缩短数秒。

传统 BIOS 启动链路 加电自检 POST(16 位实模式) 枚举 IDE / USB / 网卡等外设 读取 MBR(INT 13h,512 字节) 加载 GRUB 第一阶段 boot.img 进入 GRUB2 菜单 UEFI 启动链路 SEC → PEI → DXE 并行初始化 BDS 选择启动项(可跳过自检) 读取 + ESP(FAT32 分区) 加载 grubx64.efi(64 位保护模式) 进入 GRUB2 菜单

二、GRUB2 配置优化方法

GRUB2 的配置文件分为 /etc/default/grub(用户可编辑)和 /boot/grub/grub.cfg(由 grub-mkconfig 生成)。优化应修改前者,再执行 update-grub 或 grub-mkconfig -o /boot/grub/grub.cfg 生效。

关键优化项包括:

  • GRUB_TIMEOUT:菜单等待秒数,设为 0 可跳过菜单,设为 1~2 保留应急入口。
  • GRUB_TIMEOUT_STYLE:设为 hidden 可隐藏菜单,仅在按键时显示。
  • GRUB_DISABLE_OS_PROBER=true:禁止扫描其他操作系统,避免磁盘枚举延迟。
  • GRUB_CMDLINE_LINUX_DEFAULT:精简内核参数,移除 quiet splash 可观察真实启动日志,但会略增输出耗时。
  • GRUB_TERMINAL:设为 console 可避免图形终端初始化。
# /etc/default/grub 优化示例
GRUB_TIMEOUT=1
GRUB_TIMEOUT_STYLE=hidden
GRUB_DISABLE_OS_PROBER=true
GRUB_TERMINAL=console
GRUB_CMDLINE_LINUX_DEFAULT=""
GRUB_DISABLE_RECOVERY=true

# 生效命令
sudo update-grub
# 或
sudo grub-mkconfig -o /boot/grub/grub.cfg
若使用 UEFI,可进一步检查 /boot/efi/EFI/ 下是否存在多余启动项,使用 efibootmgr 删除无效条目,减少 BDS 阶段选择时间。

三、引导超时与菜单精简方法

引导超时和菜单项数量是影响启动感知速度的直接因素。默认 GRUB 超时为 5 秒,菜单中可能包含多个内核版本、恢复模式和 memtest 条目。精简策略如下:

  1. 将 GRUB_TIMEOUT 降至 1 秒,并设置 GRUB_TIMEOUT_STYLE=hidden。
  2. 设置 GRUB_DISABLE_RECOVERY=true,移除恢复模式条目。
  3. 清理旧内核:sudo apt autoremove --purge 或 sudo dnf remove --oldinstallonly。
  4. 若无需多系统,设置 GRUB_DISABLE_OS_PROBER=true。
  5. 使用 grub2-mkconfig 后检查 grub.cfg 中 menuentry 数量,确认精简生效。
优化项 默认值 优化值 预期收益
GRUB_TIMEOUT 5 秒 1 秒 减少 4 秒等待
GRUB_TIMEOUT_STYLE menu hidden 跳过菜单渲染
GRUB_DISABLE_OS_PROBER false true 减少磁盘扫描 1~3 秒
GRUB_DISABLE_RECOVERY false true 减少菜单项
旧内核保留数 3~5 个 1~2 个 缩短菜单生成时间

四、案例与场景:从 8 秒到 2 秒的引导优化

某台 UEFI 服务器启动耗时约 8 秒,其中固件阶段 3 秒、GRUB 菜单等待 5 秒。排查发现:GRUB_TIMEOUT=5,菜单中有 6 个内核条目,且 os-prober 扫描了 4 块磁盘。优化步骤:将超时改为 1 秒并隐藏菜单,禁用 os-prober,清理旧内核至 2 个,使用 efibootmgr 删除 3 个无效启动项。最终固件阶段降至 2 秒,GRUB 阶段降至 0.5 秒,总启动时间约 2.5 秒。

注意:将 GRUB_TIMEOUT 设为 0 且隐藏菜单后,若内核启动失败将难以进入救援模式。生产环境建议保留 1 秒超时,并确保可通过串口或 IPMI 干预。

五、误区与复盘

常见误区包括:直接编辑 /boot/grub/grub.cfg 导致更新后被覆盖;只改超时却未清理旧内核,菜单生成仍慢;在 UEFI 系统上误用 BIOS 优化手段;以及忽略固件自身设置(如 Fast Boot、CSM 兼容模式)带来的额外延迟。复盘时应使用 systemd-analyze blame 和 dmesg 时间戳确认固件与引导阶段的实际耗时,再针对性调整。

# 查看启动各阶段耗时
systemd-analyze
systemd-analyze blame | head -20

# 查看固件与引导时间
dmesg | grep -i "efi\|bios\|grub"

综上,固件与引导加载程序优化应遵循“先测量、后调整、再验证”的闭环:确认 BIOS/UEFI 模式,精简 GRUB2 配置,压缩超时与菜单项,最后通过启动日志验证收益。这一阶段的优化往往投入小、见效快,是 Linux 启动性能调优中性价比最高的环节之一。