引导程序与内核加载
复习
- 编译与解释:程序变成机器指令的两条基本道路
- 没有操作系统的程序:裸机程序在装载、设备和多程序共存上的困难
- 按下电源:复位与固件:CPU 从约定位置开始执行,固件接过控制权
TL;DR
- 引导程序的任务:把操作系统内核从磁盘装进内存,再跳过去
- 它比固件大、比内核小,仍然要小而可靠
- 内核被装入并初始化后,才真正接手管理机器
- 到这一步,启动的接力才算交到管理者手里
正文
上一章,固件从启动设备里只读了一小段代码,就跳了过去。真正的操作系统内核,还好好躺在磁盘上。
把内核请进内存的活儿,就落在这一棒——引导程序(bootloader)身上。
它为什么这么小
固件给引导程序的空间通常非常有限:老式机器上,只有磁盘的第一个扇区,几百字节。就这么点地方,既要能读磁盘,又要能找内核,实在逼仄。
所以引导程序常常分两步走:
- 先利用这一小段空间,把磁盘上更大的一段引导代码读进来
- 再由这段代码,去完成真正的加载工作
这一步一步地“把自己变大”,是引导程序里的常见套路。
把内核搬进来
接下来,引导程序要顺着磁盘上的位置,把内核映像读进内存的指定位置。
内核是一个完整的程序,有代码、有数据,可能还有压缩包和自己的一小段解压代码。引导程序负责把它原样搬到内存里预先约好的地方。
磁盘: [ 引导程序 ][ 内核映像 ][ 其它文件 ]
内存: ↑ ↑
执行它 搬到内存约定位置
搬完之后,引导程序让 PC 指向内核的入口地址,跳过去。从这一刻起,机器开始跑内核的代码——启动的控制权,正式交接。
内核初始化
内核接手时,机器还是一片“荒地”:内存管理没建立,设备没接好,中断没配置。所以它要先做一串初始化:
- 建立内存管理,弄清哪些内存可用
- 设置中断和异常处理
- 初始化设备与驱动
- 建立起调度所需的数据结构
收拾停当后,内核启动第一个进程。从此以后,程序不再直接面对硬件,而是通过内核请求服务——这正是我们下一章要说的“管理者”。
接力完成
把整条链子连起来看:
固件 → 引导程序 → 内核初始化 → 第一个进程 → 普通程序
每一棒都只干一件事:把下一棒读进来、跳过去。硬件千差万别,但这条接力链环环相扣,最终把控制权稳稳地交到了操作系统手里。
思考题
引导程序为什么要“尽量小”?如果它出了错,机器会怎样?为什么启动过程要分成固件、引导程序、内核这么多棒,而不是一步到位?
小结
知识点
- 引导程序负责把内核从磁盘装入内存并跳转
- 引导程序常常分两阶段,逐步扩大自身
- 内核初始化内存、中断、设备与调度结构
- 启动是固件、引导程序、内核层层接力的过程
参考资料
- Wikipedia(zh):启动程序:bootloader 的工作
- Wikipedia(zh):内核:操作系统内核
- Wikipedia(zh):多重引导:常见的引导程序
思考题答案(仅供参考)
引导程序要小,是因为固件给它的空间很有限,而且越小越不容易出错、加载越快。它一旦出错,后续的内核就装不进来,机器会卡在启动阶段,通常表现为黑屏或反复重启。启动之所以分成好几棒,是因为每一步面对的限制不同:固件要在硬件差异巨大的情况下找到启动设备,引导程序要在很小的空间里搬动内核,内核则要建立完整的运行环境。分工明确、逐级抽象,才让“从按下电源到运行程序”这件复杂的事变得可靠。
协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
封面图
设计师 | 南国微雪