# 计算机启动流程

计算机的启动流程如下

## 第一阶段：BIOS

上个世纪70年代初，"只读内存"（read-only memory，缩写为ROM）发明，开机程序被刷入ROM芯片，计算机通电后，第一件事就是读取它。这块芯片里的程序叫做"基本輸出輸入系統"（Basic Input/Output System），简称为BIOS。

BIOS程序是在主板上的。

**1.1 硬件自检**

各类硬件都是连接在主板上，主板上的BIOS程序首先检查，计算机硬件能否满足运行的基本条件，这叫做"硬件自检"（Power-On Self-Test）。如果硬件出现问题，主板会发出不同含义的蜂鸣，启动中止。如果没有问题，屏幕就会显示出CPU、内存、硬盘等信息。

**1.2 启动顺序**

当主板上同时连接了U盘、多个硬盘等设备时，BIOS就要决定从哪一个设备启动。可以通过设置BIOS的`Boot Sequence`来决定设备的启动顺序。BIOS按照启动顺序，把控制器移交给排名第一的启动设备。比如，我们有两块硬盘，硬盘A排名第一，那么BIOS就会加载硬盘A的第一个扇区中的代码到内存中，然后执行它，这样就把控制权交给了硬盘A。

## 第二阶段：MBR

BIOS按照"启动顺序"，把控制权转交给排在第一位的储存设备。

这时，计算机读取该设备的第一个扇区，也就是读取最前面的512个字节。如果这512个字节的最后两个字节是`0x55`和`0xAA`，表明这个设备可以用于启动；如果不是，表明设备不能用于启动，控制权于是被转交给"启动顺序"中的下一个设备。

这最前面的512个字节，就叫做"主引导记录"（Master boot record，缩写为MBR）

**2.1 MBR结构**

磁盘的第一个扇区叫MBR，总共512字节，可以分为三个部分：

* 第1 - 446字节：该区域为代码区，BIOS就是把它加载到内存中把控制器移交给它，该代码会知道如何去启动操作系统
* 447 - 510：该区域是硬盘的分区表，保存了这个硬盘的分区信息，比如有几个分区，每个分区从哪里到哪里
* 511 - 512：主引导记录签名

**2.2 分区表**

我们可以对一个磁盘进行多个分区，然后每个分区可以格式化为不同的文件系统，每个分区还可以安装不同的操作系统。

上面讲到，第一个扇区中的512字节中，分区表只占用了64字节，而每个分区的无数据需要占据16个字节，所以一个硬盘最多可以分成4个区。我们来看一下每个分区的16字节元数据

* 第1字节：如果为`0x80`，就表示该主分区是激活分区，从这个分区启动系统。四个主分区里面只能有一个是激活的
* 第2 - 4字节：该分区第一个扇区的物理位置（柱面、磁头、扇区号等等）
* 第5字节：主分区类型
* 第6-8个字节：主分区最后一个扇区的物理位置
* 第9-12字节：该主分区第一个扇区的逻辑地址
* 第13-16字节：该分区的扇区总数

最后的四个字节（"主分区的扇区总数"），决定了这个主分区的长度。也就是说，一个主分区的扇区总数最多不超过2的32次方。如果每个扇区为512个字节，就意味着单个分区最大不超过2TB。再考虑到扇区的逻辑地址也是32位，所以单个硬盘可利用的空间最大也不超过2TB。如果想使用更大的硬盘，只有2个方法：一是提高每个扇区的字节数，二是增加扇区总数。

## 第三阶段 硬盘启动

这时，计算机的控制权就要转交给硬盘的某个分区了，这里又分成三种情况

**3.1 卷引导记录（VBR）**

上一节提到，四个主分区里面，只有一个是激活的。计算机会读取激活分区的第一个扇区，叫做"卷引导记录"（Volume boot record，缩写为VBR）。

"卷引导记录"的主要作用是，告诉计算机，操作系统在这个分区里的位置。然后，计算机就会加载操作系统了。

假设在一块硬盘的两个主分区中分别安装了windows与linux系统，如果要启动哪个系统，则必须把这个系统的分区设置为活动分区。

**3.2 扩展分区和逻辑分区**

随着硬盘越来越大，四个主分区已经不够了，需要更多的分区。但是，分区表只有四项，因此规定有且仅有一个区可以被定义成"扩展分区"（Extended partition）。

所谓"扩展分区"，就是指这个区里面又分成多个区。这种分区里面的分区，就叫做"逻辑分区"（logical partition）。

计算机先读取扩展分区的第一个扇区，叫做"扩展引导记录"（Extended boot record，缩写为EBR）。它里面也包含一张64字节的分区表，但是最多只有两项（也就是两个逻辑分区）。

计算机接着读取第二个逻辑分区的第一个扇区，再从里面的分区表中找到第三个逻辑分区的位置，以此类推，直到某个逻辑分区的分区表只包含它自身为止（即只有一个分区项）。因此，扩展分区可以包含无数个逻辑分区。

但是，似乎很少通过这种方式启动操作系统。如果操作系统确实安装在扩展分区，一般采用下一种方式启动。

**3.3 启动管理器**

这种情况和卷引导记录有些相似，计算机读取"主引导记录"前面446字节的机器码之后，把控制器交换给活动分区。但是在活动分区下的操作系统中，还安装了活动管理器。即在启动活动分区的操作系统时，最先执行的是该操作系统的启动管理器。假设在另一个分区中还安装了其他的操作系统，那么我们可以在这个启动管理器中把另一个操作系统加进来，由用户选择启动哪一个操作系统。

Windows环境下，最常用的就是`Windows Boot Loader`；Linux环境中，目前最流行的启动管理器是Grub。如下，用户可以通过Linux的启动管理器选择启动哪个操作系统

![](https://1249594082-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M69DxRGxDPboxrdgg-C%2Fsync%2Fdbd0397260fb124f4235fd7241cbbfc51b21ef1e.png?generation=1588235874174932\&alt=media)

## 第四阶段：操作系统

控制权转交给操作系统后，操作系统的内核首先被载入内存。

以Linux系统为例，先载入/boot目录下面的kernel。内核加载成功后，第一个运行的程序是/sbin/init。它根据配置文件（Debian系统是/etc/initab）产生init进程。这是Linux启动后的第一个进程，pid进程编号为1，其他进程都是它的后代。

然后，init线程加载系统的各个模块，比如窗口程序和网络程序，直至执行/bin/login程序，跳出登录界面，等待用户输入用户名和密码。

至此，全部启动过程完成

## Reference

\[1] <http://www.ruanyifeng.com/blog/2013/02/booting.html>
