8.2 启动与引导过程
我们每天开机的时候,计算机从按下电源键到进入操作系统桌面,中间经历了复杂的引导过程。理解系统的启动流程,有助于我们排查系统启动故障,理解操作系统的加载和初始化过程。
系统启动的完整流程
现代计算机从加电到操作系统启动完成,大致分为以下几个阶段:
加电 → BIOS/UEFI初始化 → POST自检 → 选择启动设备 → 加载引导加载程序 → 加载内核 → 内核初始化 → 启动用户空间服务 → 登录界面
下面我们详细讲解每个阶段。
阶段1:BIOS/UEFI初始化
按下电源键后,计算机首先会运行主板上固化的固件程序:BIOS或者UEFI。
BIOS(Basic Input/Output System,基本输入输出系统)
BIOS是传统的固件接口,已经有几十年的历史:
- 存储在主板的ROM芯片中,计算机加电后首先运行
- 负责最基础的硬件初始化和自检
- 功能比较简单,使用16位模式,最大支持2.2TB的硬盘,MBR分区
- 现在新的主板已经逐渐淘汰BIOS,改用UEFI
UEFI(Unified Extensible Firmware Interface,统一可扩展固件接口)
UEFI是BIOS的替代者,是现代计算机的标准固件:
- 支持32位和64位模式,功能强大
- 支持最大9.4ZB的硬盘,GPT分区
- 图形界面,支持鼠标操作
- 支持安全启动(Secure Boot),防止恶意软件篡改引导过程
- 启动速度更快
- 兼容BIOS启动模式
POST上电自检(Power-On Self Test)
BIOS/UEFI运行后首先执行POST自检:
- 检查CPU、内存、硬盘、显卡等硬件是否正常
- 如果硬件有故障,主板会发出蜂鸣声报错,屏幕显示错误信息
- 自检通过后,初始化基本的硬件驱动(显卡、硬盘、键盘等)
选择启动设备
自检完成后,BIOS/UEFI会根据用户设置的启动顺序(U盘优先、硬盘优先、光驱优先等),尝试从对应的启动设备启动。
- 每个启动设备的第一个扇区(512字节)是引导扇区,如果最后两个字节是0x55AA,说明这个设备是可引导的
- BIOS/UEFI会把引导扇区的内容加载到内存,然后跳转到这个位置执行,把控制权交给引导加载程序
阶段2:引导加载程序(Boot Loader)
引导加载程序(Boot Loader)的作用是加载操作系统内核到内存,然后启动内核。
常见的引导加载程序
- GRUB(GRand Unified Bootloader):Linux系统最常用的引导加载程序,功能强大,支持多系统启动,可以引导Linux、Windows等系统
- Windows Boot Manager:Windows系统的引导加载程序
- systemd-boot:轻量级的Linux引导加载程序,用于systemd管理的系统
- UEFI Shell:UEFI自带的命令行Shell,可以手动执行引导命令
引导过程
以GRUB为例,引导加载程序的工作流程:
- 阶段1:BIOS/UEFI加载GRUB的第一阶段代码(存储在MBR的前446字节),功能很简单,加载第二阶段的代码
- 阶段1.5:加载文件系统驱动,这样就可以识别ext4等文件系统
- 阶段2:加载/boot分区下的GRUB配置文件,显示启动菜单,让用户选择要启动的系统或者内核版本
- 用户选择后,GRUB加载对应的内核文件和initramfs/initrd到内存
- 跳转到内核入口点,把控制权交给内核
MBR vs GPT分区表
硬盘的分区表有两种格式:MBR和GPT,和BIOS/UEFI对应。
MBR(Master Boot Record,主引导记录)
- 传统的分区表格式,和BIOS配合使用
- 存储在硬盘的第一个扇区(512字节),其中:
- 前446字节:引导加载程序代码
- 接下来64字节:分区表,最多只能记录4个主分区
- 最后2字节:魔数0x55AA,表示是可引导设备
- 最大支持2.2TB的硬盘,最多4个主分区(可以用扩展分区实现更多逻辑分区)
- 现在已经逐渐被GPT取代
GPT(GUID Partition Table,全局唯一标识分区表)
- 新一代的分区表格式,和UEFI配合使用
- 最多支持128个分区,没有主分区扩展分区的概念
- 最大支持9.4ZB的硬盘(1ZB=10亿TB)
- 有冗余备份,分区表在硬盘头尾各存一份,损坏后可以恢复
- 支持安全启动,更安全
- 是现在新硬盘的标准分区格式
initramfs/initrd
initramfs(初始RAM文件系统)是一个微型的根文件系统,打包在镜像中,和内核一起加载到内存:
- 包含了必要的驱动模块(硬盘驱动、文件系统驱动等)和工具
- 内核启动时首先挂载initramfs作为临时根文件系统
- 加载必要的驱动,然后挂载真实的根文件系统
- 切换到真实的根文件系统,启动init进程
- 作用:内核不需要包含所有硬件的驱动,减少内核体积,同时可以支持加载第三方驱动
阶段3:内核初始化
内核被加载到内存后,开始执行内核初始化:
- 内存初始化:检测系统内存大小,初始化内存管理模块
- 进程调度初始化:初始化调度器,创建0号 idle 进程和1号 init 进程
- 设备初始化:扫描所有硬件设备,加载对应的驱动程序
- 挂载根文件系统:根据引导参数指定的根分区,挂载真实的根文件系统
- 启动init进程:把控制权交给用户空间的1号init进程,内核态初始化完成,进入用户空间启动阶段
阶段4:用户空间初始化
内核启动完成后,启动用户空间的第一个进程(PID=1),负责启动所有用户空间的服务和程序。
init进程
init进程是用户空间的第一个进程,所有其他用户进程都是它的子进程:
- 传统SysV init:旧的init系统,串行启动服务,速度慢
- systemd:现在主流Linux发行版的init系统,并行启动服务,速度快,功能强大
- launchd:macOS的init系统
以systemd为例,用户空间启动流程:
- systemd作为1号进程启动,读取配置文件
- 按照依赖关系并行启动系统服务:日志服务、网络服务、文件系统挂载、数据库、Web服务等
- 启动图形界面或者登录服务,显示登录界面
- 用户登录后启动桌面环境或者Shell,系统启动完成
不同操作系统的启动流程对比
Windows启动流程
- UEFI/BIOS初始化,POST自检
- 加载启动设备的EFI分区中的Windows Boot Manager
- Windows Boot Manager读取BCD(启动配置数据),加载Windows内核(ntoskrnl.exe)
- 内核初始化,加载驱动程序
- 启动smss.exe(会话管理器)、csrss.exe(客户端运行时子系统)、wininit.exe等系统进程
- 启动服务和登录界面,用户登录后启动explorer.exe资源管理器,进入桌面
macOS启动流程
- 按下电源键,运行BootROM,初始化硬件,POST自检
- 加载EFI引导程序,然后加载macOS内核
- 内核初始化,加载驱动,启动launchd进程(PID=1)
- launchd启动系统服务和代理程序
- 启动登录窗口,用户登录后加载桌面环境
启动常见问题排查
- 开机黑屏无反应:检查电源、硬件连接,POST自检失败,硬件故障
- 提示找不到启动设备:检查启动顺序设置,硬盘是否损坏,引导扇区是否损坏
- Grub Rescue模式:GRUB配置损坏,需要修复GRUB引导
- 内核panic:内核启动失败,可能是内核损坏、驱动不兼容、硬件故障
- 启动后卡住:查看系统日志,通常是某个服务启动失败,或者磁盘挂载错误
思考问题
- BIOS和UEFI有什么区别?UEFI相比BIOS有哪些优势?
- MBR和GPT分区表各有什么优缺点?为什么GPT逐渐取代了MBR?
- initramfs的作用是什么?如果没有initramfs会怎么样?
- 系统启动时如果显示“Operating System not found“,可能是什么原因?怎么排查?