Linux内核启动:head程序执行过程
目录
教学视频
Linux内核启动:head程序开始执行(三)–分析setup_idt代码实现
1. 整体过程描述
在执行main函数之前,先要执行三个由汇编代码生成的程序,即bootsect、setup和head。之后,才 执行由main函数开始的用C语言编写的操作系统内核程序。
-
第一步,加载bootsect到0x07C00,然后复制到0x90000;
-
第二步,加载setup到0x90200。 值得注意的是,这两段程序是分别加载、分别执行的。
-
head 程序与它们的加载方式有所不同。大致的过程是
- 先将head.s汇编成目标代码,将用C语言编写 的内核程序编译成目标代码,然后链接成system模块。也就是说,system模块里面既有内核程序,又有 head程序。两者是紧挨着的。要点是,head程序在前,内核程序在后,所以head程序名字为“head”。 head程序在内存中占有25KB+184B的空间。前面讲解过,system模块加载到内存后,setup将system 模块复制到0x00000位置,由于head程序在system的前面,所以实际上,head程序就在0x00000这个位置。
- head 程序除了做一些调用 main 的准备工作之外,还用程序自身的代码在程序自身所在的内存空间 创建了内核分页机制,即在 0x000000 的位置创建了页目录表、页表、缓冲区、GDT、IDT,并将head 程序已经执行过的代码所占内存空间覆盖。这意味着head程序自己将自己废弃,main函数即将开始执行。
- 以上就是head程序执行过程的整体策略。
这里我们先来关注一下页表的标号: _pg_dir
标号_pg_dir标识内核分页机制完成后的内核页表起始位置,也就是物理内存的起始位置 0x000000。head程序马上就要在此处建立页目录表,为分页机制做准备。
2. HEAD 程序设置栈寄存器
现在head程序正式开始执行,一切都是为适应保护模式做准备。jmpi 0,8这一句已经将CS的段选择子与GDT第二个表项关联,CS段指向了0x000000。从现在开始,要将DS、ES、FS 和 GS 等其他寄存器 从实模式转变到保护模式,与G