4. 内核启动流程概览:BIOS/UEFI → Bootloader → Kernel → init 进程,dmesg 在各阶段的输出特征

Linux 系统的启动是一个多阶段、高度结构化的过程。从按下电源键到出现登录提示符,系统依次经历固件初始化、引导加载、内核解压与初始化、以及用户空间初始化四个核心阶段。理解每个阶段的职责与边界,是精准解读 dmesg 日志、快速定位启动故障的基础。

本章将拆解启动流程的四个主要阶段,并重点分析每个阶段在 dmesg 环形缓冲区中留下的“指纹”特征。掌握这些特征,你就能在数百行启动日志中迅速判断故障发生在哪个环节。

4.1 启动流程四阶段总览

下表总结了四个阶段的核心任务、时间窗口及 dmesg 输出特征:

阶段 核心任务 时间窗口 dmesg 输出特征
BIOS/UEFI 硬件自检 (POST)、选择启动设备、加载 Bootloader 按下电源键 ~ 数秒 无输出(dmesg 缓冲区尚未初始化)
Bootloader 加载内核映像与 initramfs 到内存,传递启动参数 BIOS/UEFI 完成后 ~ 1-2 秒 无输出(内核未运行,dmesg 不可用)
Kernel 解压内核、初始化子系统、驱动、挂载根文件系统 Bootloader 跳转后 ~ 5-30 秒 大量输出:时间戳从 [ 0.000000] 开始,包含 CPU、内存、设备枚举、驱动加载等
init 进程 启动 systemd/init 服务、挂载文件系统、启动用户态服务 内核初始化完成后 ~ 持续 持续输出:时间戳延续内核阶段,包含服务启动、挂载、网络配置等用户态日志
关键认知: dmesg 环形缓冲区由内核在启动早期初始化。因此,BIOS/UEFI 和 Bootloader 阶段的任何信息都不会出现在 dmesg 中。如果你在启动早期遇到黑屏或死机,需要借助主板蜂鸣器、POST 卡或串口控制台来诊断,而不是依赖 dmesg。

4.2 阶段一:BIOS/UEFI 固件初始化

这是系统启动的第一阶段。固件(BIOS 或 UEFI)负责最基本的硬件初始化和自检(Power-On Self-Test, POST)。

  • BIOS(传统):使用 16 位实模式,读取主引导记录(MBR),寻找活动分区并加载 Bootloader 的第一阶段代码。
  • UEFI(现代):使用 32/64 位模式,读取 GPT 分区表上的 EFI 系统分区(ESP),直接加载 .efi 格式的 Bootloader(如 GRUB、systemd-boot)。

dmesg 特征:无输出。 此阶段完全在 CPU 实模式或 UEFI 固件环境中运行,内核尚未接管硬件,printk 机制不存在。

故障定位提示: 如果系统在 POST 阶段失败(如无显示、连续蜂鸣),请检查硬件连接、内存条、显卡。此阶段的错误码只能通过主板诊断卡或特定 LED 灯获取,与 dmesg 无关。

4.3 阶段二:Bootloader 引导加载

Bootloader(如 GRUB 2)被固件加载后,负责定位并加载 Linux 内核映像(vmlinuz)和初始内存盘(initramfs)到内存,然后跳转到内核入口点。

Bootloader 的主要工作:

  1. 从磁盘或网络加载内核与 initramfs。
  2. 解析并设置内核启动参数(如 root=、quiet、console=)。
  3. 切换到保护模式或长模式(64 位)。
  4. 调用内核的启动协议入口。

dmesg 特征:无输出。 内核尚未执行,dmesg 缓冲区不存在。不过,GRUB 本身可以通过 grub.cfg 中的 serial 或 console 设置输出文本到屏幕或串口,但这些信息不属于 dmesg。

排查技巧: 如果系统在 GRUB 菜单之后、内核日志出现之前卡死,问题通常出在:
1. 内核映像损坏或配置错误。
2. 启动参数错误(如指定了不存在的根设备)。
3. 硬件兼容性问题(如 ACPI 表解析失败)。
此时,可以在 GRUB 菜单按 e 编辑启动项,移除 quiet 和 splash 参数,添加 earlyprintk=vga,keep 来获取早期内核输出。

4.4 阶段三:内核初始化

这是 dmesg 输出的核心阶段。内核从入口点 start_kernel() 开始,执行一系列复杂的初始化过程。dmesg 日志的时间戳从 [ 0.000000] 开始,精确到微秒。

内核初始化的关键子阶段及其 dmesg 特征:

子阶段 典型 dmesg 输出示例 说明
CPU 与架构检测 [ 0.000000] Linux version 6.1.0 ...
[ 0.000000] DMI: ...
[ 0.000000] smpboot: CPU0: Intel(R) ...
显示内核版本、编译信息、主板型号、CPU 拓扑。
内存初始化 [ 0.000000] e820: [mem 0x0000000000000000-0x000000000009ffff] usable
[ 0.000000] Memory: 16285712K/...
e820 映射显示物理内存布局,最后一行报告总内存。
中断控制器与时钟 [ 0.000000] APIC: ...
[ 0.000000] clocksource: tsc: ...
初始化本地 APIC、IO-APIC 和系统时钟源。
设备枚举与驱动加载 [ 0.123456] pci 0000:00:00.0: [8086:...] ...
[ 0.234567] ahci 0000:00:1f.2: AHCI 0001.0301 ...
PCI 总线扫描、设备发现、驱动绑定。这是日志最密集的部分。
文件系统与根设备 [ 1.234567] EXT4-fs (sda1): mounted filesystem with ordered data mode 挂载根文件系统,准备切换到用户空间。
启动 init 进程 [ 1.345678] Run /sbin/init as init process 内核初始化完成,创建第一个用户态进程。

下面这张 SVG 图展示了内核初始化阶段的主要组件调用关系与数据流:

内核初始化核心流程与组件关系 start_kernel() CPU/架构初始化 内存管理 (mm_init) 中断/时钟 (trap_init) 调度器 (sched_init) PCI 总线扫描 (pci_init) 驱动模型 (driver_init) 网络子系统 (net_init) 设备探测与驱动绑定 文件系统注册 (VFS) 块设备初始化 挂载根文件系统 启动 /sbin/init dmesg 时间戳从 [0.000000] 开始

4.5 阶段四:init 进程与用户空间初始化

内核挂载根文件系统后,在用户空间启动第一个进程——init。在现代 Linux 发行版中,init 通常是 systemd,但也可能是 SysV init 或 OpenRC。

此阶段的 dmesg 特征:

  • 时间戳连续:内核阶段的时间戳会自然延续到用户空间阶段。
  • 日志来源变化:除了内核自身的 printk 输出,用户空间守护进程(如 systemd-journald、udevd)也会通过 /dev/kmsg 或 syslog 系统调用向内核日志缓冲区写入信息。
  • 典型输出:服务启动状态、文件系统挂载(如 /home、/var)、网络接口配置、模块加载等。

示例 dmesg 输出片段:

[    1.345678] Run /sbin/init as init process
[    1.456789] systemd[1]: systemd 252 running in system mode (+PAM +AUDIT +SELINUX +APPARMOR +IMA)
[    1.567890] systemd[1]: Detected virtualization kvm
[    1.678901] systemd[1]: Detected architecture x86-64
[    1.789012] systemd[1]: Set hostname to <server01>
[    2.123456] systemd[1]: Started Journal Service.
[    2.234567] systemd[1]: Started udev Kernel Device Manager.
[    3.456789] systemd[1]: Mounting /home...
[    4.567890] systemd[1]: Started Network Manager.
分析要点: 在 init 阶段,dmesg 中的 systemd[1]: 前缀表示日志来自 systemd 进程。如果系统在此阶段挂起,应检查:
1. 关键服务(如 systemd-journald)是否启动失败。
2. 文件系统挂载是否超时(如 NFS 挂载不可达)。
3. udev 设备管理器是否卡在某个设备探测上。
使用 systemctl status 或 journalctl -xb 可以获取更详细的用户空间故障信息。

4.6 各阶段故障与 dmesg 的对应关系

下表总结了常见启动故障与 dmesg 输出阶段的对应关系,帮助你快速定位问题范围:

故障现象 可能原因 dmesg 检查点 阶段归属
黑屏,无任何输出 硬件故障、BIOS/UEFI 损坏、Bootloader 损坏 dmesg 无输出 BIOS/UEFI 或 Bootloader
GRUB 菜单后卡死,无内核日志 内核映像损坏、启动参数错误、早期 ACPI 错误 dmesg 无输出或只有 [ 0.000000] 开头几行 Bootloader → 内核早期
内核日志开始,但中途停止 驱动崩溃、硬件不兼容、内存错误 检查最后一条日志,通常在设备探测或驱动加载处 内核初始化
内核日志完整,但无法进入登录界面 根文件系统损坏、init 进程缺失、关键服务失败 检查 Run /sbin/init 之后的服务启动日志 init 进程
系统启动缓慢 设备超时、服务依赖等待、udev 规则执行慢 检查时间戳间隔,寻找长时间停顿点 内核或 init 进程

4.7 实战:从 dmesg 时间戳判断当前阶段

在分析 dmesg 输出时,时间戳是判断当前处于哪个阶段的最直接依据。以下是一个快速判断指南:

  • 时间戳 < 0.5 秒:通常处于 CPU/内存/中断等核心子系统初始化阶段。如果在此区间出现错误,往往是硬件兼容性或 ACPI 问题。
  • 时间戳 0.5 ~ 5 秒:设备枚举与驱动加载阶段。大量 PCI、USB、SATA 设备日志出现。此阶段的错误通常指向特定硬件或驱动。
  • 时间戳 5 ~ 30 秒:文件系统挂载与 init 启动阶段。如果在此区间出现长时间停顿,应检查根设备识别、文件系统完整性或 initramfs 内容。
  • 时间戳 > 30 秒:用户空间初始化阶段。服务启动、网络配置、挂载远程文件系统等。此阶段的延迟通常与 systemd 服务配置有关。
效率技巧: 使用 dmesg -T 可以将内核时间戳转换为人类可读的日期时间,便于与系统日志 /var/log/messages 或 journalctl 进行交叉比对。例如:
dmesg -T | grep -E "error|fail|warning" 可以快速筛选出带有时间信息的异常日志。

通过本章的学习,你应该能够根据 dmesg 日志的时间戳和内容特征,准确判断系统启动到了哪个阶段,从而将故障定位的范围从“整个启动过程”缩小到“某个具体阶段”,为后续的深入分析打下坚实基础。