操作系统的启动

在进行开发和实验之前,我们有必要讲一下操作系统的启动过程。操作系统(OS)的启动过程因设备类型不同(通用计算机与嵌入式设备)而略有差异。但总体上可以归纳为三阶段:

  • 第一步 板载固件:上电后,首先执行的程序便是板载固件,它可能提供了一些固件检测、配置设备的功能,但它主要还是用于加载第二步的引导程序
  • 第二步 引导阶段:引导程序(Bootloader)的主要功能是引导操作系统内核,使其能够正常运行。它还可能为内核提供启动所需的参数
  • 第三步 操作系统内核:操作系统内核被加载到内存,开始执行

固件

BIOS的概念由Gary Kildall在开发CP/M操作系统时首次提出,它的作用是为操作系统提供硬件抽象层,以便在不同硬件平台上运行,后来随着计算机软硬件技术的发展,BIOS逐渐被UEFI取代。

如今,许多通用计算机设备都自带UEFI固件,计算机上电后,首先执行UEFI固件:

  • 初始化硬件设备,例如CPU、内存、键盘、显示器等
  • 执行电源自检(POST, Power-On Self-Test),检查硬件状态是否正常
  • 查找启动设备(如硬盘、U盘、网络)并加载引导程序(Bootloader)
  • UEFI还支持图形界面、网络引导以及更大的分区表(GPT)

引导程序

在我们的常见的个人计算机中,操作系统内核通常位于磁盘的某个分区中,磁盘使用GPT、MBR分区格式。现代操作系统会使用特定的引导程序加载内核,常见的引导程序有:用于Linux内核的引导程序GRUB、嵌入式引导程序Uboot、Windows Boot Manager。

以从磁盘启动,GRUB引导为例,UEFI程序首先寻找可启动的设备,从磁盘的EFI系统分区加载引导程序,引导程序可能会提供以下的功能:

  1. 硬件初始化

    • 配置必要的硬件设备,例如CPU、内存控制器、中断控制器等

    • 为后续的系统启动做好准备,包括设置时钟频率、初始化缓存(Cache)和内存管理单元

  2. 加载操作系统内核

    • 从指定的存储设备(如硬盘、SD卡、网络或其他非易失性存储器)加载内核映像到内存中
    • 解析和加载其他必要的启动文件,例如设备树(Device Tree)、初始RAM盘(initramfs)或驱动程序
  3. 内核启动前的配置

  • 提供内核启动所需的参数,例如启动命令行参数
  • 设置内存映射或其他资源分配,确保内核在加载后能正确使用系统资源
  • 如果使用多核处理器,可能需要进行初步的多核配置
  1. 引导流程管理

    • 支持多种引导模式,例如单用户模式、调试模式、恢复模式
    • 实现引导菜单,供用户选择不同的内核或操作系统版本
  2. 错误处理

    • 在加载内核或初始化硬件过程中发生错误时,提供诊断信息或提示用户采取措施
    • 记录错误日志,便于调试和排查问题
  3. 用户交互

    • 提供用户接口,用于选择引导选项或修改引导配置
    • 一些高级引导程序还支持脚本化引导流程

操作系统内核

最后,引导程序将操作系统内核加载到内存中,并将CPU控制权交给操作系统内核,系统内核会:

  • 初始化硬件和驱动程序
  • 建立虚拟内存管理
  • 创建系统进程
  • 挂载根文件系统,启动用户空间服务,完成系统启动