linux系统启动过程
BIOS
当我们给计算机加电的时候,计算机系统怎么知道该如何启动我们的操作系统呢?
首先计算机之中在主板上,有一个东西叫ROM(Read Only Memor),在ROM上固话了一些程序,被称为BIOS(基本输入输出系统),由于系统刚刚启动时处于实模式,关于什么是实模式,以及保护模式,可以看这篇文章
实模式可操作的空间非常有限,只有2^20也就是1M的地址空间
在X86系统之中,将 1M 空间最上面的 0xF0000 到 0xFFFFF,一共64K映射给了ROM,当访问到这块地址的时候,就会访问到ROM。当加电的时候,系统加载ROM之中的BIOS之前,会完成一系列初始化工作
1. CS(代码段寄存器)置为0xFFFF
2. IP(指令指针寄存器)置为0x0000
所以对于第一条指令会指向0xFFFF+0x0000,也就是0xFFF0,处于ROM的地址空间内,这是一个JMP指令会调到ROM中执行初始化的工作,也就是开始了BIOS
BIOS会检查两件事情
1. 系统硬件是否完好
2. 建立中断向量表和中断服务程序
在BIOS阶段,也可以通过键盘的方式对BIOS发出指令,一旦通过键盘,就肯定会触发一个中断来让系统处理你的指令,所以第二个步骤是很有必要的。此时BIOS前期的工作就算完成
BootLoader
BIOS完成上述步骤后,就需要开始加载操作系统。一般的操作系统,例如在windows我们都会安装在C盘也就是硬盘上。在BIOS上我们也可以看到启动盘的选择。
启动盘的特点如下:
- 一般位于第一个扇区
- 占用512字节
- 以0xAA55结束
满足上述条件,可以称之为启动盘,并且在512字节内完成启动的相关代码。
启动盘里的代码是GRUB2(Grand Unified Bootloader Version2),定义的。也就是说BIOS执行了启动盘中由GRUB2定义好的一系列加载操作系统的步骤
可以通过 grub2-mkconfig -o /boot/grub2/grub.cfg 来定义系统启动执行的选项。这些代码
grub2定义的操作系统的步骤可以分为以下几步:
- boot.img
- diskboot.img
- lzma_decompress.img
- kernel.img
- 启动内核
boot.img
由boot.S编译而成,一共512字节,正好符合启动盘的第一个扇区的大小,所以会安装在这个第一扇区,通常这个扇区成为MBR(主引导记录扇区)
BIOS会将boot.img从硬盘加载到内存中的0x7c00来运行,因为只有512个字节,所以boot.img的唯一使命就是加载grub2的另一个镜像core.img
core.img由lzma_decompress.img,diskboot.img,kernel.img和一系列模块组成
boot.img会先加载core.img的第一个扇区,也就是diskboot.img
diskboot.img
由diskboot.S编译而成,任务是将core.img的其他部分一块加载到进来,显示解压它的下一步骤,lzma_decompress.img,再往下就是kernel.img,最后则是各个modules的映射,这里还不到linux的内核,所有都是grub的内核
lzma_decompress.img
由startup_raw.S编译而成,因为后续的kernel.img是经过压缩过后的,所以需要解压,同时它还需要完成从 实模式——>保护模式 的切换,为的是能在更大的寻址空间里,加载更多的东西
切换到保护模式,需要完成一系列动作
1、启动分段,将寄存器里的段寄存器变成段选择子(类似于索引),来指向某个段描述符(真正的段的起始地址),实现不同进程切换
2、启动分页
3、打开Gate A20,也就是第21根地址线的控制线,在8086模式下,一共只有20个地址线,总共可以访问1M的地址空间,所以保护模式需要启动第21根,来增大可以寻址的空间
资源搜索网站大全 https://www.renrenfan.com.cn
kernel.img
由startup.S及一堆C文件编译而成,startup.S会调用grub_main(grub kernel的主函数)
主函数中
1. grub_load_config解析gurb.conf文件中的配置信息
2. 选定操作系统
3. 调用grub_menu_execute_entry,解析并执行选择的那一项
4. 其中选择的那一项可能会有很多指令,例如linux16,initrd等,都会执行对应的函数
5. 调用grub_command_execute,真正启动内核