【Linux】从机器启动到内核初始化

it2022-05-05  143

声明:文章是个临时起意的小科普文,不是很严谨,建议多看文中提及的参考资料或者亲自扒Linux源码。

 

一、8086机器启动过程

该部分参考资料:

王爽《汇编语言》

李忠、王晓波《x86汇编语言:从实模式到保护模式》

于渊《一个操作系统的实现》

刘超《趣谈Linux操作系统》

 

1.1 CPU加电复位

CPU加电复位,主要是预置处理器中寄存器的初始状态。

在8086CPU中其中除了CS全部置一之外,其他的13个寄存器全部置零。这样操作的目的是为了灵活的进行jmp转移执行系统ROM(不写死,换了不同的系统或体系,只需要jmp到不同的地址即可)。

 

1.2 系统ROM(主板BIOS)

执行系统ROM程序的目的有三个:

一是硬件的自检;二是初始化系统BIOS(这一部分主要是主板BIOS,除了系统BIOS之外,还有网卡和显卡的BIOS),准备好实模式中断服务;三是初始化了系统BIOS之后,具备了IO能力,然后将硬盘的0面0道1扇区(即主引导扇区MBR,共512字节)加载到0x07c00处并执行主引导记录MBR。

 

 

(图来自《汇编语言》1.15)

 

1.3 MBR

MBR主引导扇区由三个部分组成:MBR代码、DPT和主引导扇区标记0xAA55

MBR代码:主引导记录,即主引导扇区前446字节,存储的数据是引导代码,主要是计算操作系统在硬盘中的位置,并加载执行,将权限交给操作系统(后面80X86机器这里是加载boot程序,操作系统的磁盘寻址和加载交由boot程序处理)。DPT磁盘分区表disk partition table(现在几乎都是GPT——Guid partition table),分区表指明了各个分区的起始位置、大小、类型,最重要的是标记是否为活动分区。分区表中只允许设置一个分区为活动分区,表明该分区是“可以启动的”。0xAA55是主引导记录的标志。

 

 

 

1.4 加载OS并启动内核

主引导记录代码通过分区表知道了活动分区,然后从活动分区加载DOS操作系统,然后执行操作系统代码,完成内核初始化之后,OS才算启动完成。

以上是8086机器(实模式)的启动过程。

8086机器只有实模式,保护模式是80286机器开始的。所以在80286以后的系统,在加载操作系统之前,还需要做一些从实模式进入保护模式的准备,之后才会加载操作系统。

准备进入保护模式的主要步骤:

 

二、Linux的启动过程

参考文章:https://blog.csdn.net/gatieme/article/details/50914250

刘超《趣谈Linux操作系统》

 

2.1 Linux启动的主要步骤

Linux的启动和上面8086的启动过程(80286以后的机器在启动过程中还需要做从实模式进入保护模式的准备)有很多相似的地方。但是Linux的启动过程不再只是MBR去加载DOS系统那么简单,现在的操作系统太大了。Linux的启动过程之前是GRUB引导程序来引导的,现在是GRUB2。

GRUB2工具是一个来自GNU项目的OS启动引导程序,可以通过修改其配置文件grub.cfg,对一些启动过程自定义。

比较Linux和8086的启动过程:在8086机器的四个步骤中,CPU加电复位和BIOS之后就是MBR和加载操作系统,但是在Linux启动过程中,在CPU加电复位和BIOS之后,就由GRUB2来负责了。

Linux启动的主要步骤:

CPU加电复位;系统BIOS(系统ROM);GRUB2过程(可以通过grubs-install来安装grub2启动程序);加载操作系统,初始化内核,Linux启动完成;

 

2.2 GRUB2过程的主要步骤

GRUB2过程中涉及的主要步骤如下图:

其中:

boog.img就相当于8086过程中的MBR(但是boot.img是镜像文件,grub2会解压成boot.s代码,之后跳转执行),也是512字节,结构、行为和MBR一样。所以boot.img所做的也很有限,要想加载core.img,需要boot.img跳转并将控制权交给diskboot.img。diskboot.img的主要功能就是加载core.img的其他部分;lzma_decompress.img会调用real_to_prot跳转到保护模式;kernel.img中的代码会选择并加载指定操作系统,然后启动并初始化Linux内核。

 

三、Linux kernel初始化

该部分参考资料:

刘超《趣谈Linux操作系统》

Daniel P.bovet、Marco Cesati《深入理解Linux内核》(主要是附录)

Wolfgang Mauerer《深入理解Linux内核架构》(主要是附录)

 

3.1 体系结构相关的设置

参考第一部分的内容。

 

3.2 start_kernel高层设置

start_kernel完成Linux内核的初始化工作。

init_task:初始化0号进程idle;trap_init:初始化系统中断和陷阱(系统调用相关的做准备);mm_init:初始化内存管理模块:sched_init:初始化进程调度模块;rest_init:初始化用户态所有进程的祖先进程init,init会监视其他用户线程;初始化内核态所有线程的祖先kthreadd进程,kthreadd负责调度和管理所有内核线程。

 

附注:本文如有错漏,烦请指正,谢谢。


最新回复(0)