0. 概述
从我们按下电脑的电源开始,到我们进入到系统是一个非常复杂的过程,我根据我自己对一些文档的理解,尝试从自己的角度出发来记录一下我的收获。
1. 从按下电源开始
从刚接触到电脑开始,就听过一个名词叫做 BIOS,但是,仅仅是耳熟,具体干什么的一直都不清楚。即使是后来上大学学了专业课之后,知道了全程是 Basic Input/Output System 之后,到现在也没记住它具体是干什么的。
这里就自己再复习一遍,所谓的 BIOS 就是存放在 ROM(现在可能是 DPROM)中的一段代码(基本上是汇编写的,现代的似乎参杂了少量的 C),用于初始化硬件设备,并且引导启动程序。OK,这里有一些细节的东西很重要,我想来探讨一下:
- 开机之后,只有 CPU 是可以正常工作的,那么第一条指令是如何被获取并执行的
- 从开机到系统选择中间的过程是怎么样的
2. 第一条指令
给机器加上电之后,内存控制器还没有初始化,这个时候内存是不可用的。而 CPU上电后第一条指令是通过 CS:IP 寄存器来指定的,CPU 厂家会给其初始值,对于 386 处理器来说,CPU 第一条指令地址是 0xFFFFFFF0。此时对 CPU 的指令解码的对象不是北桥,CPU 发出的地址被传递到南桥并由 FHW (Firmware Hub) 解码到 BIOS ROM 芯片上。
这样,CPU 就开始了从 ROM 加载指令并且执行,直到系统初始化阶段,BIOS 会解压 BIOS Image 到 RAM 中。具体操作为编程北桥控制器对 0xE0000~0xFFFFF(128K) 置为 write only,这样对该区域的写被传递到 DRAM 里,然后把解压的 BIOS 拷贝到 E 段和 F 段,最后重新编程北桥控制器对 0xE0000~0xFFFFF 置为 read only。对于 PCI ROM BIOS,BIOS 会把每个卡上的 ROM 拷贝到 0xC0000~0xDFFFF 然后执行他们的初时化代码。
BIOS ROM 可以很大,但不都是可执行的,如含有 ACPI Table 等,开始解压到 0xE0000~0xFFFFF 只是其中一部分,在启动过程中还需要从 BIOS ROM 解压代码到 RAM 中,并覆盖其中不需要的代码。这个就好像 BIOS ROM 是硬盘(不过可用直接访问),真正执行的代码在 RAM 中一样。硬盘可以很大但 RAM 小,这也就是程序的局部性原理。
3. BIOS 操作
当 BIOS 运行起来之后,就要检查硬件是否符合要求,这个部分叫 “硬件自检(Power-On Self-Test/ POST)”,这就是 BIOS 里面的逻辑了,可以跳过。
有时在自己重装系统的时候,开机会听到一些滴滴声,并且电脑启不起来,然后会将内存啥的拔出来擦一擦,再插回去就好了,这其实就是硬件自检的部分,而不同的 “滴滴” 声代表不同的含义,在现在的一些主板其实都直接有错误码可以看了,让定位硬件问题方便了许多。
4. 加载引导程序
硬件自检完成后,BIOS 就要加载启动程序了,也就是我们安装了多系统的时候,可以选择要启动哪个系统的界面。但是,在到这一步之前,我们平时在装机的时候还有一个场景就是,假设我们有硬盘,还有一个 CDRom,CDRom 里面放的是我们要安装的系统镜像,那么 BIOS 是如何知道是否可以从硬盘 / CDRom 开始启动的呢?
这里有一个我们是确定的,那就是先从 CDRom 还是先从硬盘尝试,因为在装机的时候我们经常要操作这个,可以自己选择或者直接在 BIOS 中修改。
图 1:选择启动设备 |
---|
BIOS 会尝试读取这个设备的第一个扇区(512 Byte),看最后两个字节是否是 “0x55 0xAA”,如果是,那么这就是所谓的 MBR(主引导分区),表示可以启动;如果不是,继续回到 BIOS,尝试下一个设备:
图 2:Boot Order |
---|
图片来自于: 第一课 操作系统的简介及上电引导过程 |
5. 加载操作系统
当 BIOS 成功引导到了操作系统之后,那么就会将操作系统的引导程序加载到内存中,然后置寄存器到对应的内存地址,从而开始将系统的操作逻辑交给操作系统。
需要注意的是,在这一个系列中,CPU 都是处于实模式下,也就是说,没有虚拟内存的存在,所有 CPU 访问的地址都是实际的地址,直到 OS 的引导程序初始化完之后进入到保护模式。
至此,就进入到了操作系统的情况,关于开机的启动引导就告一段落了,后续我会接续了解一下 GRUB 以及 Linux 系统的真正启动流程,先留一坑。