以下内容来自【腾讯元宝】。
理解Linux的启动过程,就像阅读一本精彩的侦探小说,线索环环相扣。为了让这个故事更清晰,我们先用一个表格来梳理从电脑开机到系统就绪的全过程中,几个关键"角色"的登场顺序和核心任务:
阶段顺序 | 阶段名称 | 核心任务与关键组件 |
---|---|---|
1 | 固件初始化 (BIOS/UEFI) | 硬件自检(POST),查找并加载引导程序 |
2 | 引导加载程序 (Boot Loader) | 加载内核与初始化内存盘(initramfs),如GRUB2 |
3 | 内核初始化 (Kernel) | 初始化系统核心功能,驱动硬件,创建第一个用户进程 |
4 | 初始化系统 (Init System) | 接管启动过程,启动系统服务,如systemd |
5 | 用户登录 (User Login) | 提供登录界面,完成用户认证,启动用户会话 |
下面,我们就从最初的Linux版本开始,详细讲述这段"旅程"的演进。
⏳ 原始版本的启动之旅
早期Linux内核(如0.11版本)的启动过程紧密依赖于x86架构的实模式,过程非常精巧,可以看作是一段"自我复制"和"模式切换"的舞蹈。
-
BIOS与引导扇区 (bootsect.s)
计算机加电后,CPU运行在实模式下。BIOS (基本输入输出系统)首先进行硬件自检,然后将硬盘第一个扇区(引导扇区)的内容载入内存地址
0x7C00
处,并将控制权交给这里的代码------由bootsect.s
汇编程序编译而成。它的首要任务是将自己从0x7C00
搬运到更安全的0x90000
地址,为后续代码腾出空间。 -
setup.s:数据收集与模式切换
bootsect.s
接着将紧随其后的setup.s
模块(负责读取内存大小、磁盘参数等机器系统数据)和更大的system
模块(包含内核主体)加载到内存中。随后跳转到setup.s
执行。setup.s
的主要职责包括:- 获取硬件参数:利用BIOS中断获取系统硬件信息。
- 准备保护模式 :开启A20地址线 以访问1MB以上的内存,然后设置关键数据结构全局描述符表(GDT) 和中断描述符表(IDT) 的寄存器。
- 切换至保护模式:通过设置控制寄存器CR0的PE位,CPU从16位实模式切换到32位保护模式,从而能够访问更大的内存空间并使用虚拟内存等高级功能。之后通过一个长跳转,正式进入保护模式下的代码执行。
-
head.s:内核的正式入口
跳转后,执行的是
system
模块最前端的head.s
。可以把它看作是内核在保护模式下的"入口仪式",主要负责:- 重新设置GDT和IDT。
- 初始化内存分页机制,为内核建立简单的页表,实现线性地址到物理地址的映射。
- 完成这些最底层的初始化后,
head.s
会调用main.c
中的main()
函数,内核正式进入用C语言书写的主初始化阶段。
-
main.c与init:用户态的起点
在
main()
函数中,内核进行了大量初始化工作:陷阱门、中断处理、块设备驱动、内存管理、调度程序等。所有这些完成后,内核会手动切换到用户态 ,创建出系统的第一个进程------进程0(PID 0),然后通过fork
系统调用创建进程1(PID 1),进程1通常执行init
程序,从而开启用户空间,最终提供一个Shell界面供用户交互。
🔄 关键的技术演进
随着硬件和应用需求的变化,Linux的启动流程也发生了显著演变。
-
引导加载程序的统一:GRUB的出现
早期需要手动将
bootsect.s
和setup.s
写入磁盘引导扇区,繁琐且易出错。功能强大、配置灵活的GRUB 等引导加载程序的出现,接管了bootsect.s
和setup.s
的绝大部分职责。它能够直接识别文件系统,加载压缩的内核镜像,并自行完成保护模式切换等复杂任务,大大简化了启动配置。 -
固件接口的革新:从BIOS到UEFI
- 传统BIOS:功能简单,存在启动速度慢、不支持大硬盘(2TB限制)、安全性差等局限性。
- 现代UEFI:取代了传统BIOS,提供了更快的启动速度、图形化预启动环境、安全启动机制以及对GPT分区表的原生支持,从而突破了2TB硬盘的限制。现在的GRUB2通常作为一个EFI应用程序存放在EFI系统分区中,由UEFI固件直接加载。
-
初始化系统的现代化:从SysV init到systemd
- SysV init:传统的初始化系统,采用顺序、串行的脚本启动方式,启动速度较慢。
- systemd :现代Linux发行版广泛采用的初始化系统。它采用并行启动 服务的方式,大幅提升启动速度;使用单元文件 进行服务管理和依赖关系控制,功能更强大。
systemd
作为第一个用户进程(PID 1)启动,并管理整个系统的服务生命周期。
🚀 现代Linux的启动流程
现代的Linux启动流程可以概括为:
- UEFI/BIOS初始化:硬件自检并加载引导程序。
- 引导加载程序(GRUB2)阶段 :UEFI从ESP分区加载GRUB2的EFI应用程序。GRUB2加载核心内核镜像
vmlinuz
和初始内存文件系统initramfs
到内存。initramfs
是一个临时的根文件系统,包含了启动早期所必需的内核模块(如磁盘控制器、文件系统驱动),确保内核能够访问真正的根文件系统。 - 内核初始化 :内核解压自身并初始化。内核挂载
initramfs
,并执行其中的/init
脚本,加载必要的驱动模块。找到真正的根文件系统后,将其挂载,并卸载initramfs
。内核启动第一个用户空间进程,在现代系统中通常是systemd
(PID 1)。 - systemd初始化阶段 :
systemd
接管后续启动过程,并行启动系统服务,并建立指定的目标,如图形界面或命令行界面,最终启动登录管理器或终端,等待用户登录。
💎 总结
Linux的启动过程是一部从"简单直接"到"强大稳健"的演进史。
- 原始版本的启动过程紧密依赖硬件,展现了操作系统如何"白手起家"的精妙控制。
- 现代版本则在继承核心思想的基础上,通过UEFI、GRUB2、systemd等组件,实现了更快的速度、更强的功能与更好的安全性。
希望这篇文章能帮助你清晰地理解Linux的启动机制。如果你对某个特定阶段或组件有更深入的兴趣,我们可以继续探讨。