Linux系统的启动过程

Lear 2025-08-11 14:00:00
Categories: Tags:

Linux系统的启动过程

Linux系统的启动过程是一个精心设计的接力过程,涉及多个阶段,从硬件初始化到用户空间服务的完全启动。下面进行详细深入分析:

核心阶段概述

  1. 硬件初始化 (BIOS/UEFI)
  2. 引导加载程序 (Boot Loader)
  3. 内核初始化 (Kernel Initialization)
  4. initramfs (Initial RAM Filesystem)
  5. 用户空间初始化 (Systemd / SysV init / etc.)
  6. 登录管理器 / Shell

阶段 1:硬件初始化 (BIOS/UEFI)

  1. 电源开启 (Power On): 用户按下电源按钮。
  2. POST (Power-On Self-Test):
    • 主板固件(BIOS或UEFI)执行硬件自检。
    • 检查关键硬件组件:CPU、内存、显卡、存储控制器、键盘等是否正常工作。
    • 如果检测到严重错误,会通过蜂鸣声或屏幕错误码提示。
  3. 固件初始化 (Firmware Initialization):
    • 配置硬件:初始化CPU、内存控制器、芯片组、总线(PCIe, USB, SATA等)、时钟。
    • 枚举连接的设备(存储设备、网卡、USB设备等)。
    • 建立硬件设备列表和访问方式(如中断、I/O端口、内存映射)。
  4. 选择启动设备 (Boot Device Selection):
    • 根据固件设置的启动顺序(Boot Order),查找可启动的设备(硬盘、SSD、USB驱动器、网络PXE等)。
    • BIOS:查找每个设备第一个扇区(512字节)末尾的引导签名 0xAA55(Magic Number)。找到签名即认为该设备可引导,并加载该扇区(MBR)到内存 0x7C00 处执行。
    • UEFI:查找EFI系统分区(通常是FAT32格式),然后在该分区下按照特定路径(如 \EFI\ubuntu\grubx64.efi)查找并直接加载EFI应用程序(Boot Loader的可执行文件)。UEFI本身理解分区表和文件系统,无需加载MBR。
  5. 移交控制权 (Handover):
    • 硬件平台初始化完成。
    • 将控制权移交给从选定启动设备加载的第一阶段引导加载程序(BIOS是MBR,UEFI是EFI Application)。

关键点:

阶段 2:引导加载程序 (Boot Loader)

主要任务: 找到并加载操作系统内核(vmlinuz-xxx)和可选的初始RAM磁盘映像(initrd.img-xxx 或 initramfs-xxx.img),并将控制权交给内核。

常见引导加载程序:GRUB2 (Grand Unified Bootloader version 2)

  1. GRUB2 的阶段 (BIOS 环境):
    • Stage 1 (MBR): 被BIOS加载到 0x7C00 执行。其代码量极小,主要目的是加载Stage 1.5。它通常嵌入在MBR中或紧跟在MBR之后的扇区中。
    • Stage 1.5: 位于MBR之后到第一个分区开始前的间隙(通常约31KB)。它包含了访问常见文件系统(如ext2, ext3, ext4, FAT)的基本驱动。它的核心任务是找到并加载位于 /boot/grub 目录下的 Stage 2 核心映像(core.img)。
    • Stage 2 (core.img): 被加载到内存中。它提供了完整的GRUB功能:解析配置文件 /boot/grub/grub.cfg,显示引导菜单,允许用户选择操作系统或内核版本,加载模块(如支持LVM、RAID、加密、网络引导等)。其核心任务是加载Linux内核映像initramfs 映像到内存中。
  2. GRUB2 配置文件 (grub.cfg):
    • 要加载的内核文件路径(如 /boot/vmlinuz-5.15.0-86-generic)。
    • 要加载的 initramfs 文件路径(如 /boot/initrd.img-5.15.0-86-generic)。
    • 传递给内核的命令行参数(root=, ro, quiet, splash, init=, 特定驱动参数等)。
    • 根文件系统所在设备(在 initramfs 接管前可能需要)。
    • 通常由工具(如 grub-mkconfig, update-grub)根据 /etc/default/grub 和 /etc/grub.d/ 下的脚本自动生成。
    • 定义了引导菜单项、默认选项、超时时间。
    • 每个菜单项指定了:
  3. 加载内核和 initramfs:
    • GRUB2 利用其文件系统驱动(或Stage 1.5)从 /boot 分区读取 vmlinuz-xxx 和 initrd.img-xxx 文件到内存的特定位置。
    • GRUB2 设置好内核启动所需的基本运行环境(如内存布局、视频模式)。
  4. 移交控制权给内核:
    • GRUB2 执行一个特殊的跳转指令,将CPU控制权交给内存中已加载的Linux内核映像的入口点(通常是 startup_32 或 startup_64,取决于架构)。
    • 同时,它将包含引导参数(cmdline)、内存磁盘地址(initramfs位置)、硬件信息(如BIOS内存映射)等数据的引导信息结构体(如struct boot_params on x86)传递给内核。

关键点 (UEFI):

阶段 3:内核初始化 (Kernel Initialization)

内核开始执行,接管硬件控制权,进行复杂的初始化工作,目标是挂载真正的根文件系统(/)并启动第一个用户空间进程(通常是 /sbin/init)。

  1. 解压与设置 (Architecture-Specific Setup):
    • 设置CPU运行模式(x86: 从实模式/保护模式切换到长模式/64位模式)。
    • 初始化基本内存管理:设置页表,启用分页(MMU)。
    • 设置中断描述符表(IDT)和全局描述符表(GDT)。
    • 检测CPU特性(FPU, MMX, SSE, etc.)。
    • 初始化控制台(早期打印输出)。
    • 内核通常是压缩的(如 vmlinuz 是 bzImage 格式)。内核入口代码首先解压自身到内存高端。
    • 进行极其底层的、与CPU架构相关的初始化:
  2. 通用内核初始化 (start_kernel()): 这是内核C语言代码的入口点(init/main.c)。进行一系列关键子系统初始化:
    • 初始化 RCU (Read-Copy Update): 高性能同步机制。
    • 初始化定时器 (tick_init(), time_init()): 设置系统时钟和定时器中断。
    • 初始化控制台 (console_init()): 如果之前是早期控制台,现在初始化完整控制台驱动。
    • 初始化模块子系统 (module_init()): 支持可加载内核模块(LKM)。
    • 初始化/proc, /sys等虚拟文件系统 (vfs_caches_init(), proc_root_init()).
    • 初始化安全框架 (security_init()).
    • 初始化设备模型 (do_basic_setup()->driver_init()): 建立设备、总线、驱动程序的模型,为后续探测硬件做准备。
    • 在 start_kernel() 的末尾,调用 rest_init()。
    • rest_init() 使用 kernel_thread() 创建内核线程 kernel_init (这就是未来的1号进程 /sbin/init 的内核线程部分)。
    • rest_init() 创建另一个内核线程 kthreadd (2号进程,负责创建其他内核线程)。
    • rest_init() 自身最终调用 cpu_startup_entry() 成为 0号进程 (idle 进程)
    • 初始化伙伴系统(物理页帧分配器)。
    • 初始化虚拟内存管理(VM)。
    • 解析并保留引导信息中传递的物理内存布局。
    • printk() 初始化: 建立内核日志缓冲区。
    • 陷阱和中断初始化: 设置异常处理程序,初始化中断控制器(如APIC/IOAPIC)。
    • 调度器初始化 (sched_init()): 初始化进程调度器数据结构,创建0号进程 (idle 进程或 swapper 进程)。这是内核创建的第一个“进程”,它运行在内核空间,当CPU空闲时执行。
    • 内存管理初始化 (mm_init()):
    • 创建 init 进程上下文 (rest_init()):
    • 其他重要初始化:
  3. 挂载根文件系统 (rootfs):
    • 内核在初始化早期会在内存中挂载一个最小的、内存中的根文件系统 (rootfs)。这通常是一个 tmpfs 或 ramfs。
    • 这个初始 rootfs 为内核后续操作(如加载模块、访问 initramfs)提供了一个基础的文件系统环境。
  4. 处理 initramfs (populate_rootfs()):
    • 内核检查引导参数是否指定了 initramfs,以及GRUB是否加载了它。
    • 如果存在 initramfs,内核将其解压并提取到刚刚挂载的初始 rootfs 中。这通常会覆盖 rootfs 中的部分内容。
    • 这个解压出来的内容就是 initramfs 映像包含的文件和目录结构,它提供了在内核挂载真实根文件系统之前所需的关键工具、驱动和脚本。
  5. 移交控制权 (kernel_init):
    • 内核执行 kernel_init 内核线程(即1号进程的内核部分)。
    • 如果存在 initramfs,kernel_init 会尝试执行 initramfs 根目录下的 /init 程序(这是一个用户空间程序,尽管此时还没有完整的用户空间环境)。
    • 如果没有 initramfs 或 /init 执行失败,内核会尝试直接执行指定的根文件系统上的 /sbin/init, /etc/init, /bin/init, /bin/sh 等(通过 root= 参数指定根设备)。
    • 此时,内核将控制权交给用户空间的第一个程序 (/init 或 /sbin/init),标志着内核初始化阶段的结束和用户空间初始化的开始。

关键点:

阶段 4:initramfs (Initial RAM Filesystem)

initramfs 是一个临时的、基于内存的根文件系统。它的主要职责是为内核挂载真正的根文件系统 (/) 做准备,处理那些需要在内核启动后但在访问真实根设备之前完成的任务。

  1. /init 程序执行:
    • 内核启动 initramfs 中的 /init 程序(通常是一个shell脚本或可执行文件,如BusyBox init)。
    • 这个程序是 initramfs 运行时的核心控制流程。
  2. 关键任务:
    • 这是 initramfs 的最后一步也是最关键的一步。
    • 将当前进程的根目录从 initramfs 切换到新挂载的真实根文件系统 (/root)。
    • 卸载或释放旧的 initramfs 占用的内存。
    • 使用加载好的驱动和工具访问根设备(由内核参数 root= 指定)。
    • 执行 mount 命令将真实的根文件系统挂载到 initramfs 内的某个目录(通常是 /root)。
    • 组装软件RAID (mdadm)。
    • 激活LVM卷组 (vgchange -ay)。
    • 解锁加密卷(请求密码或读取密钥文件)(cryptsetup luksOpen)。
    • 处理网络根文件系统(NFS)。
    • 加载必要的内核模块: 加载访问根设备所需的驱动(如SCSI控制器驱动、RAID驱动、LVM驱动、加密驱动 dm-crypt 用于LUKS分区、文件系统驱动如 ext4, btrfs, xfs 等)。这些驱动可能不在内核镜像中,而是作为模块打包在 initramfs 里。
    • 设备发现与等待: 探测硬件,可能需要等待慢速设备(如USB存储)就绪。
    • 处理复杂存储:
    • 挂载真正的根文件系统:
    • 切换根 (pivot_root / switch_root):
  3. 执行真正的 init:
    • 切换根成功后,initramfs 的 /init 程序(或它调用的脚本)会执行真实根文件系统上的 /sbin/init(或内核参数 init= 指定的程序)。
    • 控制权正式移交给真实根文件系统上的初始化系统(如systemd, SysV init)。
    • initramfs 的使命完成,其占用的内存通常会被回收。

关键点:

阶段 5:用户空间初始化 (Systemd / SysV init / etc.)

真正的根文件系统挂载后,第一个用户空间进程 /sbin/init (通常是 systemd 或 SysV init 的符号链接) 开始运行。它负责启动所有用户空间的服务、守护进程、设置登录环境等。这里以systemd(现代主流发行版标准)为例:

  1. systemd 进程启动 (PID 1):
    • 作为内核直接启动的 /sbin/init,成为系统的1号进程,是所有其他用户空间进程的祖先。
    • 它读取其配置文件 /etc/systemd/system.conf 和 /usr/lib/systemd/system.conf。
  2. 确定启动目标 (default.target):
    • graphical.target: 图形界面多用户模式。
    • multi-user.target: 文本界面多用户模式。
    • rescue.target: 单用户救援模式。
    • systemd 启动的目标是达到一个预定义的“状态”(target)。默认启动目标通常是一个符号链接,指向例如:
    • 默认目标由 /etc/systemd/system/default.target 符号链接指定。
  3. 并行启动与服务管理:
    • Socket Activation: 按需启动服务。当有连接到达监听socket时,才启动对应的服务。避免服务闲置占用资源。
    • D-Bus Activation: 类似Socket Activation,基于D-Bus消息激活服务。
    • Mount & Automount Units: 管理文件系统挂载点。
    • Path Activation: 监控文件路径变化来触发服务启动。
    • systemd 的核心优势是并行启动服务,显著加速启动过程。
    • 它通过定义服务之间的依赖关系(在 .service, .socket, .target 等单元文件中声明)来决定启动顺序。
    • 关键机制:
    • systemd 读取 /etc/systemd/system/ (系统管理员配置) 和 /usr/lib/systemd/system/ (发行版默认配置) 目录下的单元文件(.service, .target, .socket, .device, .mount, .timer 等)。
  4. 启动流程概要:
    • 如果目标是 graphical.target,则继续启动其依赖的服务:显示管理器(如gdm.service, lightdm.service, sddm.service)。
    • 显示管理器负责启动X Server或Wayland Compositor,并显示登录窗口。
    • 所有定义为 multi-user.target 依赖的服务(如网络、远程登录sshd、打印cups、cron等)都启动完成。
    • 系统进入命令行多用户模式,可以接受文本登录。
    • 日志服务 (systemd-journald):收集和管理内核及服务日志。
    • 网络服务 (systemd-networkd, NetworkManager):配置网络接口、IP地址、路由。
    • 认证服务 (systemd-logind):管理用户登录会话。
    • 定时器服务 (systemd-timedated)。
    • D-Bus 系统总线 (dbus.service):进程间通信总线。
    • 挂载 /proc, /sys, /dev, /dev/pts, /run 等虚拟文件系统。
    • 设置hostname、locale、时钟(NTP)、内核参数 (sysctl)、加载内核模块(通过 .mount 和 .service 单元)。
    • 激活swap空间。
    • 初始化udev:管理 /dev 下的设备节点,处理热插拔事件。udev 规则在 /etc/udev/rules.d/ 和 /usr/lib/udev/rules.d/ 下。
    • 设置随机数生成器种子。
    • 基础系统初始化:
    • 启动核心系统服务:
    • 到达基本多用户状态 (multi-user.target):
    • 到达图形界面状态 (graphical.target):
  5. 依赖解析与状态维护:
    • systemd 持续监控所有单元的状态。
    • 如果服务崩溃,systemd 可以配置为自动重启。
    • 提供强大的命令(systemctl, journalctl)管理服务、查看日志、分析启动性能。

SysV init (传统方式) 对比:

阶段 6:登录管理器 / Shell

  1. 文本登录 (如果目标是 multi-user.target):
    • 系统启动 getty 服务(如 agetty)。
    • getty 在虚拟终端 (tty1-tty6) 上显示 login: 提示符。
    • 用户输入用户名和密码。
    • 认证过程(通常通过 PAM - Pluggable Authentication Modules)。
    • 认证成功后,启动用户指定的登录 shell (如 /bin/bash, /bin/zsh),通常在 /etc/passwd 中定义。
    • shell 读取并执行其配置文件(如 .bashrc, .zshrc)。
  2. 图形登录 (如果目标是 graphical.target):
    • 启动一个用户会话管理器(如 gnome-session, startplasma-x11, sway)。
    • 会话管理器加载用户的桌面环境(DE)或窗口管理器(WM),启动相关的用户级程序(面板、文件管理器、设置守护进程等)。
    • 执行用户的自动启动程序(~/.config/autostart/, ~/.xinitrc 等)。
    • 显示管理器 (DM) 启动并显示图形登录界面。
    • 用户选择用户并输入密码。
    • 认证(同样通过PAM)。
    • 认证成功后,DM:
    • 用户进入图形桌面环境。

总结与可视化流程

+————————–+
| Power On |
+————+————-+
|
v
+————————–+
| BIOS/UEFI Firmware |
| - POST |
| - HW Init |
| - Find Boot Device |
+————+————-+
| (Loads MBR / EFI App)
v
+————————–+
| Boot Loader (GRUB2) |
| - Loads menu |
| - Loads kernel & initramfs |
+————+————-+
| (Hands off to kernel entry point)
v
+————————–+
| Linux Kernel |
| - Decompress self |
| - Arch-specific setup |
| - start_kernel() |
| * Core subsystems |
| * Create PID 0, 1, 2|
| - Mount rootfs (tmpfs) |
| - Extract initramfs |
| - Run /init (PID 1) |
+————+————-+
| (User space begins)
v
+————————–+
| initramfs /init |
| - Load modules (drivers)|
| - Assemble RAID/LVM |
| - Unlock crypto |
| - Mount real root (/) |
| - pivot_root/switch_root|
| - Exec /sbin/init |
+————+————-+
| (Real root FS)
v
+————————–+
| Systemd (PID 1) |
| - Parse unit files |
| - Start base system |
| - Reach default.target |
| - Start services |
+————+————-+
|
+——————-> [multi-user.target] —> Getty —> Login Shell
| (Text Login)
|
v
+——————-> [graphical.target] —> Display Manager —> Desktop Session
(Graphical Login)

深入理解 Linux 启动过程对于系统管理员至关重要,它能帮助: