引言
近期比较忙碌,本系列的文章依然是在持续更新,而本文将从宏观的角度来探讨一下计算机的启动过程,希望对你有所启发。
Hi,我是 sharkChili ,是个不断在硬核技术上作死的 java coder ,是 CSDN的博客专家 ,也是开源项目 Java Guide 的维护者之一,熟悉 Java 也会一点 Go ,偶尔也会在 C源码 边缘徘徊。写过很多有意思的技术博客,也还在研究并输出技术的路上,希望我的文章对你有帮助,非常欢迎你关注我的公众号: 写代码的SharkChili 。
因为近期收到很多读者的私信,所以也专门创建了一个交流群,感兴趣的读者可以通过上方的公众号获取笔者的联系方式完成好友添加,点击备注 "加群" 即可和笔者和笔者的朋友们进行深入交流。
详解计算机启动步骤
硬件初始化和POST自检
众所周知,CPU的基本工作流程无非是:
- 提取指令电路提取指令
- 解析指令电路进行指令解析
- 执行电路执行指令
- 回写电路负责将数据回写
计算机启动通电后,所有的电路都会重置到已知的初始状态。主板芯片组会向CPU发送重置信号,CPU将寄存器设置为预定义的初始值。随后CPU开始执行固化在BIOS/UEFI芯片中的程序,首先进行POST(Power-On Self-Test)自检过程,检测内存、CPU、显卡等关键硬件是否正常工作。期间如果存在报错就会将错误写入到EAX中,所以操作系统启动时会查看EAX是否非0
在实模式下,CPU需要从内存中加载必要的启动数据。由于此时还处于实模式(Real Mode),CPU访问内存使用的是物理地址,通过段地址+偏移地址的方式进行寻址。MMU(内存管理单元)在保护模式下才会启用,而启动初期CPU工作在实模式下。
16位寄存器的段+偏移寻址方式计算步骤如下:
- 段寄存器为16位,可以表示0-65535个段
- 偏移地址为16位,每个段内可以寻址0-65535个字节
- 8086处理器有20根地址线,物理地址通过段地址左移4位(乘以16)加上偏移地址计算得出
- 物理地址 = 段地址 × 16 + 偏移地址
- 最大寻址空间 = 0xFFFF × 16 + 0xFFFF = 0x10FFEF,但由于8086处理器只使用20根地址线,所以实际可寻址空间是2^20 = 1,048,576字节 = 1MB
而1MB的内存空间,难免显得有些局促。
BIOS启动和CS:IP执行
完成硬件初始化后,内存中还没有操作系统数据。BIOS芯片中的程序被映射到内存的固定地址空间,CPU根据预设的CS:IP寄存器值获取第一条要执行的指令。在8086处理器中,CPU复位后CS寄存器被设置为0xFFFF,IP寄存器被设置为0x0000,因此第一条指令的物理地址为0xFFFF0,这正好指向BIOS芯片映射的地址。
CPU从这个地址开始执行BIOS程序,BIOS程序的第一条指令通常是跳转指令(jmp),跳转到BIOS程序的主要执行部分,然后:
- 继续进行硬件检测和初始化
- 初始化中断向量表IVT(Interrupt Vector Table,实模式下的中断表)
在多核系统中,通常1号CPU作为引导处理器(Bootstrap Processor, BSP)进行必要的初始化工作。BIOS程序完成硬件检测后,会根据启动顺序查找可启动设备。当找到硬盘等启动设备后,BIOS会加载硬盘的第一个扇区(主引导记录MBR)到内存的0x7C00地址处。MBR是硬盘的0磁头0柱面1扇区,大小为512字节。
为了确保MBR的有效性,BIOS会检查MBR的最后两个字节是否为0x55和0xAA(称为引导签名),这是MBR有效的标志。如果验证通过,BIOS将控制权转移给MBR中的引导代码,开始操作系统的加载过程。
切换到保护模式和多核启动
当引导加载程序完成操作系统内核的加载后,会切换CPU到保护模式(Protected Mode)。在保护模式下,CPU可以访问更大的内存空间,并启用内存管理单元(MMU)。
切换到保护模式的过程包括:
- 初始化全局描述符表(GDT)
- 设置控制寄存器CR0的PE位(Protection Enable)
- 初始化页目录和页表
- 启用分页机制
完成保护模式切换和MMU初始化后,CPU和内存的交互进入新的阶段。在多核系统中,引导处理器(BSP)完成初始化后,会通过特定的协议(如APIC)唤醒其他核心CPU,使它们开始并行工作。
小结
来简单小结一下计算机的启动过程:
- CPU通电后进行必要的检查和寄存器重置,开始执行BIOS程序
- BIOS进行POST自检和硬件初始化,然后加载MBR到内存
- MBR中的引导代码加载操作系统内核
- 操作系统内核初始化,切换到保护模式并启用MMU
- 引导处理器唤醒其他CPU核心,开始多核并行工作
Hi,我是 sharkChili ,是个不断在硬核技术上作死的 java coder ,是 CSDN的博客专家 ,也是开源项目 Java Guide 的维护者之一,熟悉 Java 也会一点 Go ,偶尔也会在 C源码 边缘徘徊。写过很多有意思的技术博客,也还在研究并输出技术的路上,希望我的文章对你有帮助,非常欢迎你关注我的公众号: 写代码的SharkChili 。
因为近期收到很多读者的私信,所以也专门创建了一个交流群,感兴趣的读者可以通过上方的公众号获取笔者的联系方式完成好友添加,点击备注 “加群” 即可和笔者和笔者的朋友们进行深入交流。
参考
《趣话计算机底层技术》
本文使用 markdown.com.cn 排版