操作系统中的系统启动过程(Boot Process)
字数 2751 2025-12-06 12:38:01

操作系统中的系统启动过程(Boot Process)

今天我们来详细讲解计算机操作系统的启动过程,也称为引导过程。这是从按下电源键到操作系统完全就绪、等待用户交互的复杂链条。理解它有助于你深入认识计算机的硬件初始化、固件作用和操作系统内核的加载机制。

核心目标:将存储在非易失性存储介质(如硬盘、SSD)上的静态操作系统内核代码和数据,加载到易失性主内存中,并让CPU开始执行内核代码,最终建立起一个可以运行用户程序的系统环境。

这个过程是分层接力的,每一阶段都由一个更复杂的程序将控制权移交给下一阶段。典型的x86架构启动流程可分为以下几个关键步骤:

第一步:通电与固件初始化

  1. 事件:按下电源键,主板通电。
  2. 硬件自检:主板上一个专用芯片(如Intel的Management Engine或ARM的类似组件)启动,进行最基本的上电自检,确保CPU、芯片组等关键硬件有供电且能响应。
  3. CPU复位:CPU从特定的、硬连线的复位向量地址开始取指执行。在x86系统中,这个地址是0xFFFFFFF0,位于主板上的一块只读存储器中。
  4. 执行固件:这个ROM里存储的是固件程序,如今最常见的是UEFI,早期是BIOS。CPU开始执行固件代码。
  5. 固件职责
    • 硬件初始化:对主板上的核心硬件(如内存控制器、系统时钟、基本输入输出设备)进行初始化,使其进入一个可工作的已知状态。
    • 自检:进行更全面的加电自检,检测内存大小、存储设备、外设等。
    • 寻找引导设备:按照预设的顺序(如UEFI启动菜单设置)检查各个存储设备(硬盘、U盘、网络等),寻找有效的引导加载程序

第二步:引导加载程序阶段

  1. 主引导记录:在传统的BIOS+MBR方案中,固件会读取启动设备的第一个扇区(512字节),即主引导记录。MBR的结构是:
    • 引导代码:占446字节,是一段小程序。
    • 分区表:占64字节,描述磁盘的4个主分区。
    • 魔数0x55AA,占2字节,用于标识有效的MBR。
  2. 执行MBR引导代码:固件将MBR的引导代码加载到内存的0x7C00地址,并跳转执行。这段小程序的任务很简单:在分区表中找到活动分区,然后加载并执行该分区第一个扇区的代码,这个扇区称为卷引导记录
  3. 现代方式:在UEFI系统中,过程更直接。UEFI固件本身支持文件系统驱动(如FAT32)。它会直接查找存储在EFI系统分区(一个特定格式的FAT分区)中的可执行文件,通常是\EFI\BOOT\BOOTx64.EFI。这个.efi文件就是UEFI引导加载程序,如GRUB2、Windows Boot Manager。
  4. 引导加载程序的职责:无论通过MBR还是UEFI,此时控制权已移交给了功能更强大的引导加载程序。它的核心任务是:
    • 加载操作系统内核映像:从硬盘的特定位置,将操作系统的内核映像文件(如Linux的vmlinuz,Windows的ntoskrnl.exe)读取到内存中指定的地址。
    • 解压内核:许多内核映像是压缩的,引导加载程序需要先将其解压到正确位置。
    • 设置启动参数:为内核准备一个启动信息块,里面包含了内存布局、根文件系统位置、命令行参数等关键信息,并将这个信息块的地址告知内核。
    • 切换CPU模式:例如,在x86-64系统上,引导加载程序需要将CPU从实模式(16位)切换到保护模式(32位),再切换到长模式(64位),以便内核能在高权限的64位模式下运行。

第三步:内核初始化

  1. 跳转至内核入口:引导加载程序完成上述工作后,跳转到内核映像的入口点,将控制权彻底交给操作系统内核。
  2. 内核早期初始化:内核代码开始执行,此时它处于一个非常“原始”的环境。
    • 架构相关初始化:初始化CPU、中断控制器、内存管理单元等。建立最基本的页表,开启虚拟内存分页机制
    • 解压自身:如果是压缩内核,此时会完成自解压。
    • 解析启动参数:读取并解析引导加载程序传递过来的启动信息块。
    • 探测硬件:识别系统中所有的CPU核心、内存总容量、PCI总线上的设备等。
  3. 内核核心子系统初始化:内核开始初始化其各个子系统,这是一个自底向上的过程:
    • 调度器初始化:建立进程0(idle进程)和进程1(未来的init进程)的数据结构,启动时钟中断,使调度器可以工作。
    • 内存管理子系统初始化:基于探测到的物理内存,建立完整的伙伴系统slab分配器等,将内核自身占用的内存标记为已用,其余内存纳入系统的内存管理。
    • 虚拟文件系统初始化:初始化VFS,为后续挂载根文件系统做准备。
    • 设备驱动初始化:按照顺序初始化核心的、必须的驱动程序,如控制台、存储控制器驱动等。
  4. 挂载根文件系统:根据启动参数指定的位置(如root=/dev/sda1),调用相应的文件系统驱动(如ext4),将存储设备上的根分区挂载到内核的根目录/。这是关键一步,此后内核才能从磁盘加载更多的驱动和程序。

第四步:用户空间初始化

  1. 启动第一个用户进程:内核初始化完成后,会尝试执行第一个用户空间程序。在现代Linux系统中,这通常是/sbin/init,或者是systemdupstart等初始化系统的程序。内核态的工作至此基本完成。
  2. 执行初始化系统init程序开始运行,它是所有用户进程的祖先。它的主要任务是:
    • 执行启动脚本:运行一系列脚本(如/etc/rc.d/rc.sysinit),配置网络、主机名、挂载其他文件系统、设置系统环境变量等。
    • 启动守护进程:根据运行级别,启动各种系统服务,如sshdcrondgetty等。
    • 建立终端getty程序会在虚拟终端上显示登录提示。
  3. 用户登录:用户在终端输入用户名和密码,getty启动login程序验证身份,成功后启动用户指定的shell

总结流程
通电 -> CPU执行固件(UEFI/BIOS) -> 固件加载并执行引导加载程序(GRUB等) -> 引导加载程序加载并跳转到内核 -> 内核初始化硬件和核心子系统 -> 内核挂载根文件系统并启动第一个用户进程(init/systemd) -> 初始化系统启动各项服务 -> 显示登录界面,系统启动完成

这个过程完美体现了计算机系统的“自举”特性:一个非常简单的程序(固件)加载一个复杂一点的程序(引导加载程序),后者再加载一个极其复杂的程序(操作系统内核),最终由内核建立起一个能够运行任意程序的完整环境。

操作系统中的系统启动过程(Boot Process) 今天我们来详细讲解计算机操作系统的启动过程,也称为引导过程。这是从按下电源键到操作系统完全就绪、等待用户交互的复杂链条。理解它有助于你深入认识计算机的硬件初始化、固件作用和操作系统内核的加载机制。 核心目标 :将存储在 非易失性存储介质 (如硬盘、SSD)上的静态操作系统内核代码和数据,加载到 易失性主内存 中,并让CPU开始执行内核代码,最终建立起一个可以运行用户程序的系统环境。 这个过程是 分层接力 的,每一阶段都由一个更复杂的程序将控制权移交给下一阶段。典型的x86架构启动流程可分为以下几个关键步骤: 第一步:通电与固件初始化 事件 :按下电源键,主板通电。 硬件自检 :主板上一个专用芯片(如Intel的Management Engine或ARM的类似组件)启动,进行最基本的上电自检,确保CPU、芯片组等关键硬件有供电且能响应。 CPU复位 :CPU从特定的、硬连线的 复位向量 地址开始取指执行。在x86系统中,这个地址是 0xFFFFFFF0 ,位于主板上的一块 只读存储器 中。 执行固件 :这个ROM里存储的是 固件 程序,如今最常见的是 UEFI ,早期是 BIOS 。CPU开始执行固件代码。 固件职责 : 硬件初始化 :对主板上的核心硬件(如内存控制器、系统时钟、基本输入输出设备)进行初始化,使其进入一个可工作的已知状态。 自检 :进行更全面的 加电自检 ,检测内存大小、存储设备、外设等。 寻找引导设备 :按照预设的顺序(如UEFI启动菜单设置)检查各个存储设备(硬盘、U盘、网络等),寻找有效的 引导加载程序 。 第二步:引导加载程序阶段 主引导记录 :在传统的BIOS+MBR方案中,固件会读取 启动设备 的第一个扇区(512字节),即 主引导记录 。MBR的结构是: 引导代码 :占446字节,是一段小程序。 分区表 :占64字节,描述磁盘的4个主分区。 魔数 : 0x55AA ,占2字节,用于标识有效的MBR。 执行MBR引导代码 :固件将MBR的引导代码加载到内存的 0x7C00 地址,并跳转执行。这段小程序的任务很简单:在分区表中找到 活动分区 ,然后加载并执行该分区第一个扇区的代码,这个扇区称为 卷引导记录 。 现代方式 :在UEFI系统中,过程更直接。UEFI固件本身支持 文件系统驱动 (如FAT32)。它会直接查找存储在 EFI系统分区 (一个特定格式的FAT分区)中的可执行文件,通常是 \EFI\BOOT\BOOTx64.EFI 。这个 .efi 文件就是 UEFI引导加载程序 ,如GRUB2、Windows Boot Manager。 引导加载程序的职责 :无论通过MBR还是UEFI,此时控制权已移交给了功能更强大的 引导加载程序 。它的核心任务是: 加载操作系统内核映像 :从硬盘的特定位置,将操作系统的 内核映像文件 (如Linux的 vmlinuz ,Windows的 ntoskrnl.exe )读取到内存中指定的地址。 解压内核 :许多内核映像是压缩的,引导加载程序需要先将其解压到正确位置。 设置启动参数 :为内核准备一个 启动信息块 ,里面包含了内存布局、根文件系统位置、命令行参数等关键信息,并将这个信息块的地址告知内核。 切换CPU模式 :例如,在x86-64系统上,引导加载程序需要将CPU从 实模式 (16位)切换到 保护模式 (32位),再切换到 长模式 (64位),以便内核能在高权限的64位模式下运行。 第三步:内核初始化 跳转至内核入口 :引导加载程序完成上述工作后,跳转到内核映像的入口点,将控制权彻底交给操作系统内核。 内核早期初始化 :内核代码开始执行,此时它处于一个非常“原始”的环境。 架构相关初始化 :初始化CPU、中断控制器、内存管理单元等。建立最基本的页表,开启 虚拟内存 和 分页机制 。 解压自身 :如果是压缩内核,此时会完成自解压。 解析启动参数 :读取并解析引导加载程序传递过来的启动信息块。 探测硬件 :识别系统中所有的CPU核心、内存总容量、PCI总线上的设备等。 内核核心子系统初始化 :内核开始初始化其各个子系统,这是一个 自底向上 的过程: 调度器初始化 :建立进程0(idle进程)和进程1(未来的init进程)的数据结构,启动时钟中断,使调度器可以工作。 内存管理子系统初始化 :基于探测到的物理内存,建立完整的 伙伴系统 、 slab分配器 等,将内核自身占用的内存标记为已用,其余内存纳入系统的内存管理。 虚拟文件系统初始化 :初始化VFS,为后续挂载根文件系统做准备。 设备驱动初始化 :按照顺序初始化核心的、必须的驱动程序,如控制台、存储控制器驱动等。 挂载根文件系统 :根据启动参数指定的位置(如 root=/dev/sda1 ),调用相应的 文件系统驱动 (如ext4),将存储设备上的根分区挂载到内核的根目录 / 。这是关键一步,此后内核才能从磁盘加载更多的驱动和程序。 第四步:用户空间初始化 启动第一个用户进程 :内核初始化完成后,会尝试执行 第一个用户空间程序 。在现代Linux系统中,这通常是 /sbin/init ,或者是 systemd 、 upstart 等初始化系统的程序。内核态的工作至此基本完成。 执行初始化系统 : init 程序开始运行,它是 所有用户进程的祖先 。它的主要任务是: 执行启动脚本 :运行一系列脚本(如 /etc/rc.d/rc.sysinit ),配置网络、主机名、挂载其他文件系统、设置系统环境变量等。 启动守护进程 :根据运行级别,启动各种系统服务,如 sshd 、 crond 、 getty 等。 建立终端 : getty 程序会在虚拟终端上显示登录提示。 用户登录 :用户在终端输入用户名和密码, getty 启动 login 程序验证身份,成功后启动 用户指定的shell 。 总结流程 : 通电 -> CPU执行固件(UEFI/BIOS) -> 固件加载并执行引导加载程序(GRUB等) -> 引导加载程序加载并跳转到内核 -> 内核初始化硬件和核心子系统 -> 内核挂载根文件系统并启动第一个用户进程(init/systemd) -> 初始化系统启动各项服务 -> 显示登录界面,系统启动完成 。 这个过程完美体现了计算机系统的“ 自举 ”特性:一个非常简单的程序(固件)加载一个复杂一点的程序(引导加载程序),后者再加载一个极其复杂的程序(操作系统内核),最终由内核建立起一个能够运行任意程序的完整环境。