好 在刚才的描述当中
我们说清楚了计算机在启动的时候
它从什么地方去读第一条指令
从磁盘上的什么地方去读第一块数据
那接下来 我们会把刚才这个过程做进一步的细化
也就是说系统启动的时候的流程
按照我们刚才说的流程
应该说我加电之后去读BIOS
BIOS去读你的加载程序
加载程序去读内核映像
这个过程实际上我们又可以把它细化下去
因为我在加载程序的时候
我BIOS里头起来
我们说直接去读bootloader
但实际上这个过程它并不能直接进行
比如说我们在最早的时候
系统里只有一个分区
上来之后我就直接到分区里找文件系统了
但是对于我们现在来说
所有的计算机
或者大多数的计算机里头都不止一个分区
可能会有几个分区
每个分区上会装不同的系统
那这个时候就在前边加上一个主引导记录
这个主引导记录是说
我要从哪个文件系统里
去读我的这个加载程序
好 有了主引导记录之后
然后我就进到当前哪个分区里头
分区里头又有一个分区的引导扇区
这个活动分区的引导扇区
再来加载我们刚才说到的加载程序
这个过程当中实际上我们就需要知道中间
这几个部分它的格式是什么样子
如果你不知道这个格式的话
那你写出来的程序
最终存到磁盘上
机器是不能够从里头认识的
那我们具体说起来呢
有这样几个过程
首先我们在前面已经说过
CPU加电完成它的初始化
到一个确定的状态去读第一条指令
我们需要知道CPU初始化之后
它的代码段段寄存器
和当前指令指针寄存器这两个的内容
算出来它的第一条指令在内存当中的什么地方
有了这个之后 说我们在这里头呢
这是它计算的依据
因为它是实模式
所以是CS和IP都是16位的
CS左移四位加在一起算出我的位置
这个时候 我放到内存当中的BIOS的位置
只能是在最底下的一兆
原因在于这时候它是20位的地址
有了这个之后我们就直接进到BIOS里执行
BIOS里 我们刚才说
它是从磁盘上去读你的加载程序
那实际上在这里头它还有很多的事情要做
首先第一个是硬件自检
也就是说我们有可能加电起来之后
你的内存出错 那整个后边就没法做
这时候问大家
你见到过你的计算机如果内存出错了
你的显示器肯定是不工作的
那这时候我怎么知道出这个问题了
我们说在计算机系统里头
它的加电自检
它上来之后是看最关键的这几个部分是不是在工作
如果说检测到
这就相当于在自检的时候你需要知道
关键的内存 显卡这几部分是否存在
或者说干脆你的机器里就没有显卡
如果存在的话 它的工作状态是什么样子
把这些设备完成每一个
这些关键性的接口卡里头
它自己也有自己的初始化程序
这些初始化程序完成之后
那我就认为关键的设备是可以的了
然后这时候 我们再来执行系统的初始化
BIOS的初始化 这时候它是干什么呢
我们说我们现在的系统
很多都是可以即插即用的
那如果说我想从一个USB接口的光驱里启动
那你怎么启得来
那这时候呢 在这个BIOS里的自检
现在是能够做到系统的自检
把这些检测并且配置你的这些即插即用的设备
这些工作做完之后
我就知道我现在的系统里到底都连了哪些硬件
好 我们说在BIOS里有一个系统配置表
这个配置表就是我们这里所说的
ESCD 就是扩展系统配置数据
那用这个数据 我就能知道
我当前系统里都有些什么样的设备
每次加电之后有可能你会插上新的卡
或者说拔掉已有的卡
这个数据是会变得
每次加电的时候都必须做
做完之后说我就把控制权
转到我们从外部读进来的数据里头
读进来的代码里
那这就是按我们在BIOS里指定的顺序
从软盘 硬盘或者光盘或者你指定的其他设备上
读进你的第一块扇区
读进来之后 那这时候
我们说在我们现在说的这个过程里头
有多个分区
好 这时我就有一个主引导记录
在这个主引导记录里头
我们需要知道的内容是它的格式
那说在里头呢
我们说它有512字节
但是在这 你只能说我可以用到的是446
那其他部分是什么
原因在于我在这里头
我还有后边有多个分区的时候
这些分区的状态是什么样的
你也要存到这512字节里头
所以这样的话
你就只有446个字节的内容来执行你的启动代码
在这启动代码里我需要干啥呢
需要知道我这些分区表是不是正确的
如果说你的分区表是错的
那这时候我的程序是没法正常加载的
然后还要加载并跳转到
你的活动分区的引导记录上去
第二个是你的分区表
然后我们对于所有的引导扇区
都有一个结束标志
这个结束标是55AA
有了这个之后 它才认为这是一个合法的主引导记录
那有了这个之后
它就会跳到你活动分区的引导扇区上去
那在这仍然是一样的
它也有一个它需要了解的格式
那在这里头 就开始有文件卷的信息
这个结束标志跟刚才那个主引导记录是一样的
好 在这基础上呢
说它有启动代码
那启动代码就是一条跳转指令
那这个跳转指令跟我们刚才说到的有什么区别呢
那这地方它就跟平台相关了 你的CPU不同
这个地方这条指令肯定也是不一样的
然后空下的其他地方呢
再是我的启动代码
这个地方的启动代码就需要认识你的格式说
我这个加载程序不是存在在512字节里头的
存在别处 它在哪
那就靠你这里的代码来约定说我放在哪
而这里的代码实际上是我们存在硬盘上的
或者说你的软盘上的
这个时候我是可以改动的
那改动完了之后
我就可以把我的加载程序放在任意的地方
只要我在这标识出来我上哪去认识它就可以
好 接下来我们说加载程序的细化
那在这里头呢
我们说加载程序它首先不是直接去加载你的内核
而是去从文件系统当中
这时候加载程序我是能够认识文件系统的格式的
从里头读一个启动配置文件
这个启动配置文件
在不同的操作系统里它是会不一样的
你比如说Windows和Linux都有自己的格式
这样的话它Windows和Linux
都有自己的加载程序的格式
依据这个选择你启动的这种参数
比如说我是在正常启动
还是说我是在安全模式启动
还是说我是在一个调试状态下启动我的系统
那这些区别都会读出来之后
它导致我在加载内核的时候的一些内核会不一样
或者说我加载的时候的参数会不一样
好 依据配置去加载内核
那么到这 我们把这个过程描述清楚了
说到这是不是会说
是说的足够详细吗
如果说我要来写实际程序
知道这些是不是就足够了
那我可以告诉大家
我这的介绍仍然是很粗的
如果说你要想写实际的程序
那么我们需要知道CPU的手册
它在加电的时候
处于什么样的状态 BIOS里的规范
我在从磁盘上什么地方读的第一条
它的格式是什么样子
那到这呢 你还需要知道
我的内核编译的时候
它的一些相应的信息
那我们说在计算机启动的过程当中
我们有很多需要考虑的因素
这种考虑的因素又有很多细节
和我们实际的硬件环境
或者说周围的情况密切相关
那是不是我们需要在每一种硬件平台上
我都要制定一个自己的启动流程呢
那实际上不是这样的
我们在实际的工业界
它制定的一组相应的标准
BIOS就是我们现在广泛使用的
在PC机上的启动流程标准
那在这里头 它是主板上的一段程序
那它可以完成系统的启动
但是从它最早出现的时候
是70年代后期
那在这应该是几十年的变化过程当中
它已经有了许多的发展
这呢 我们列出了几种它的变化
刚才说到那个主引导记录这一部分
这一部分实际上相当于是说最早的BIOS
它是从主板上加电自检之后
进到你的磁盘上的唯一的一个分区上
去加载它的引导记录去了
那有了多分区磁盘之后
就相当于我一个系统有多个磁盘 有多个分区
那这时候我就需要选择从哪个分区启动
由于这种需求呢
在上边加了一个主引导记录
这个主引导记录呢
告诉你我从这几个分区里的选择了
其中的活动分区来进行启动
那这也有了我们这里的第一个
然后从这里头我们也可以看到
当时谁在里头呢
主引导记录里头我只能描述最多四个分区
每个占16个字节
我全部有512个字节
你四个分区用到了64
那再多了的话不行了
而我们现在用到计算机很多的分区会大于四个
那这时候怎么办呢
这时候就有了这里说的GPT
全局唯一标识分区表
这个分区表 可以在我的分区表里
描述更多的分区结构
有了这个之后 我就不会受那四个的限制
所以这是BIOS的两个发展
然后PXE实际上是网络启动的一个标准
也就是说我的机器启来了之后
我想通过局域网或者说其他的网络
连到服务器上 去从服务器上
下载我的内核镜像来执行
那这时候怎么办呢
就是这是它的标准
那如果从这个角度来讲
你要从网络启动
好 这时候就你的BIOS里加网络协议栈
那从这个角度来讲的话
这个BIOS的功能也会越做越复杂
甚至于在一些系统里头
那它就是一个小的操作系统
好 那在这个变化的过程当中呢
从我们刚才讲解注意到
BIOS它可以有一些局部的修改
来完善对后续的支持
但这种支持总是会受到前边的制约
比如说在我们的主引导记录里头
为了支持多分区
那我就把中间那地方加成了磁盘上的主引导记录
然后再加上活动分区里头的这个引导记录
多了两层 实际上多这两层呢
它的意义并不是特别的必要
如果说我设计一个全新的话
那这件事情我是不需要这么做的
正是由于这种原因
那我们又定义了一种新的这个启动规范
那就是UEFI 统一可扩展固件接口
这个接口 它想达到的目标是在所有平台上
一致的提供操作系统的启动服务
为了做到这一点呢
实际上它这个标准呢
应该是从90年代就开始出它的第一个版本
一直到现在呢
都在不断的演变的过程当中
在上这课之前呢
我查了一下它的最新状态
它的最后一次修改我能看到的是2015年的1月份
好 在这里它会增加什么呢
那我在这举一个例子
说我们要想从磁盘上启动
我只要能拿到一张新的磁盘塞到你的机器里
这台机器剩下的事情我就都可以控制
那这样的话 我这个系统
对于一些关键性的服务器
我允许这样做是有麻烦的
好 针对这种麻烦
在这个UEFI规范里头呢
就定一个可信启动流程
在这个流程里头呢
BIOS起来以后
它在读磁盘上的引导记录的时候
那它是会对这个引导记录的可信性进行一个检查
也就是说它会让里头有一个签名
你只有我满足我签名的这些引导记录我才会读进来
才会把控制权交给你
使得我在整个的启动流程当中
可信的这些介质上的这些代码
可以在我的系统当中运行
从而提高了从启动的阶段
减少了这种安全的风险
那我们说 这个修改的过程
还会再继续下去
随着这个周边环境的变化
在这个规范里头加新的内容
慢慢的 也会希望这个规范能够有更广泛的适用范围