1 内核镜像
在讲解 Linux 内核启动流程之前,先需要了解一下内核镜像的组成。Linux 内核映像由 boot、setup、system 等三部分组成。在存储设备(软盘、硬盘或光盘)中的分布如下图所示,boot 处于设备的引导扇区、接下来的2-5各个扇区用于存储 setup。剩余扇区用于存储 system。
2 模块执行顺序
在 linux 启动时,首先是 BIOS 执行,将 boot 加载到内存, boot 加载 setup 到内存,然后 setup 加载 system到内存,并准备好系统启动环境,执行 system 启动系统。
3 系统启动前具体流程
在 BIOS 之后,到系统初始化的过程,其主要过程如下图所示:
注意:图中空白区域表示当前可使用内存
按照图中的执行步骤,有以下说明:
- BIOS在进行上电自检等基础工作后,加载启动盘中,第一个引导扇区,即 bootsect 所在位置,将boot 加载到 0x7c00位置。
注意:此时处于实模式,系统所能访问的内存仅限于 1M 以内。
- 此时 CPU 执行权限已经从 BIOS 转移(通过间接跳转 jmpi 0, 0x7c0)到了 boot,boot 首先执行自转移,将 boot 转移到 0x9000。
注意:此处进行转移的原因是,后期 system 将放置到 0x10000 处,从而为 system 的放置提供足够的空间。
- boot 利用 bios 中断 读取硬盘,将 setup 和 system 模块都加载内存中。其中 setup 加载到 0x90200,system 加载到 0x10000。
注意:为何此处分了 boot 和 setup 两个部分? 因为 boot 的大小存在限制,必须小于 510 个字节。
- 读取显示设备和存储设备参数,并将 system 移动到 0x00000处。读取的设备参数存放于 0x90000H 处,因为此时 boot 代码的功能和使命已经完成,无需继续存在。
为何第 3 步不直接将 system 加载到 0x00000 处? 因为,system 硬盘加载时需要用到 bios 中断,而 bios 的中断向量表就位于 0x00000-0x
00400。
- setup 执行完毕后,cpu 就将进入保护模式。进入保护模式是间接跳转指令
jmpi 0, 8
完成。
注意:
进入保护模式有以下工作需要完成:
1. 切换中断,将 bios 中断 切换为 pc 中断。
2. 建立临时 gdt,用于保护模式的间接跳转。其中 gdt 的数据描述符和代码描述符均为 0x0000H - 0x07FFH。
3. 初始化中断描述符寄存器和全局描述符寄存器, lgdt, lidt。
4. 打开 A20 地址线,使得 1M 以上的内存可访问。
5. 设置 PE 使能位。
- 进入 head 执行,设置系统需要的 页目录表、页表、中断描述符表、全局描述符表等。
注意:
1、setup 跳转到 system 时,sp 指向 0x00000H,从 head.s 的代码中也可以看出,head的开始位置startup_32:
位于head 的开始位置即 0x00000处。
2、 从代码中可以看出,gdt 和 idt 位于 head 代码的末端。
3、 页表和页目录将位于 0x00000H-0x00200H,将覆盖部分 head.s代码。
4、此处还要完成启动内存页管理机制。
- 从head.s 跳转到 main.c 中执行,前面的跳转都是通过
jmpi
指令完成,而此处的跳转是通过 ret 指令完成,借助 ret 和 堆栈 跳转到 _main 函数开始系统初始化工作。
网友评论