• Linux系统内核main函数执行之前


    1、linux是一个操作系统在机器加电后,需要从硬件通过一个引导程序加载os kernel,那么在os kernel的main函数运行之前,都发生了什么呢?

    (1)引导BIOS(存储在ROM芯片中,ROM:只读存贮器,现在一般为闪存)的启动(准备实模式下的中断向量表和中断服务程序)

    实模式:Intel80x86系列的一种cpu运行模式,特点,20位地址寻址(1MB),可直接访问BIOS和周边的硬件,没有硬件支持的实时多任务和分页机制。

    BIOS任务:把os 加载到RAM(随机存取存储器,也就是常见的内存条)

    所有的cpu在加电时强行进入16位实模式,此时cpu的一些特殊值:

    CS:0xF0000,IP:0xFFF0 所以起始地址为CS:IP   =   0xFFFF0也就是BIOS的地址。

    CS:代码段寄存器

    IP:指令指针寄存器(IP对应16位,EIP对应32位,RIP对应64位)

    指令的地址:代码段其实地址+指令段内偏移地址 = CS + IP

    中断向量表的位置:0x00000 ~ 0x003FF (一共1kb):一共256个中断向量(CS:IP),每个4B(CS:2B;IP:2B)

    BIOS数据区:0x00400 ~ 0x004FF

    中断服务程序:0x0E50B ~ 0x0FFFE

    中断int

    (2)加载第一部分kernel代码(bootsect)

    BIOS收到int 0x19,转到中断服务程序0x0E6F2(启动加载服务程序的入口地址):把第一扇区的512B代码加载到内存制定位置(0x07C00)

    (3)加载第二部分代码:

    首先规划内存,然后拷贝自身从0x07C00 到0x90000

    (DS/ES/FS/GS/SS段寄存器,SP栈顶指针)

    然后是int 0x13,将setup.s这一部分代码加载到内存0x90200处。

    bootsect和setup.s是紧紧连在一起的此时SS:SP的值是0x9FF00

    (4)加载系统模块

    bootsect利用int 0x13加载系统模块,执行加载任务的主要程序read_it ,将约120KB的内容加载值0x10000(SYSSEG)处

    然后确认一下根设备号,根文件系统设备(root device):系统中利用工具做出一个文件系统并加载至本机。

    (5)通过jumpi 0,SETUPSEG:跳转至setup.s(0x90200)处,执行setup

    利用BIOS提供的中断服务程序从设备读取机器系统数据,从0x41 和 0x46 处读取 硬盘参数表1 和 硬盘参数表2 ,分别放置在

    0x90080 和 0x90090 处 

    系统的数据加载到内存:0x90000-0x901FD total:510B

    开始实模式到保护模式的变化

    (6)关闭中断(CPU IF位:0)

    开中断和关中断(cli 和 sti)

    复制内核到内存的0x00000处(释放BIOS的中断向量表和中断服务程序,然后移动内核)

    设置中断描述符表 和 全局描述符表 (IDT 和 GDT),

    中断描述符表寄存器(IDTR)

    全局描述符表寄存器(GDTR)系统中唯一存放段寄存器内容的数组,配合保护模式下的寻址

    ************************************************************************************************

    存放任务的局部描述符表(LDT)地址 和 任务状态段(TSS)地址 完成进程各段的寻址,进城现场的保护与恢复

    GDTR标示GDT的入口,一般用LGDT将GDT基地址加载到GDTR

    IDT:中断服务程序的入口地址。

    IDTR:保存IDT的起始地址。(LIDT指令完成)

    *************************************************************************************************

    (7)打开A20,实现32位寻址(否则,即在16位模式下,超范围寻址将导致寻址回滚)

      32位寻址:最大寻址空间4GB

    执行head.s

    首先认识一下可编程中断控制器:8259A:单片可管理8级向量优先级中断(可联级,最多管理64级向量中断)

    int 0x00 ~ int 0x1F   内部中断(不可屏蔽) 和 异常中断

    保护模式下:IRQ0x00 ~ IRQ0x0F 对应中断号:int 0x20 ~ int 0x2F

    设置保护模式的代码:

    mov ax,#0x0001

    lmsw ax

    此时cr0寄存器第0位:PE置1

    跳转到head.s入口结束setup开始执行head文件。

    注:x87:数学协处理器,外置可选(从486之后一般改为内置)。

    将head.s 汇编成目标代码,c语言kernel编译成目标代码,连接成system模块。    

    其中head:

    25KB + 184B

    head在0x000000位置创建也目录表,页表,缓冲区,GDT,IDT(占用覆盖head已经执行过的代码)

    内核起始位置0x000000 _pg_dir (页表目录起始位置)

    重建一套GDT,因为源GDT内存位置将被覆盖。

    检查数学协处理器

    最后的准备:

    L6标号和main函数入口地址压栈,L6是main函数异常退出时的程序转接点:程跳转到setup_paging去建立分页机制。

    一页:4KB

    Main函数入口:0x064b8

    全局描述符表:0x05cb8

    中断描述符表:0x054b8

    剩余184B:0x05400

    软盘缓冲区:0x05000

    页表3到页表0的起始:0x01000 0x03000 0x02000 0x01000

    页表目录:0x00000

    Pg位CR0寄存器第31位:控制分页。

    CR3寄存器:分页机制虚拟地址到物理地址的映射。

    然后开始调用main。

  • 相关阅读:
    轻松记账工程冲刺第一天
    课堂练习-找水王
    NABCD模型—轻松记账
    四则运算网页版
    二维数组最大子数组(结对开发)
    软件工程结对作业01
    返回一个二维整数数组中最大联通子数组的和
    学习进度条(第六周)
    整数数组中最大子数组的和
    学习进度条(第五周)
  • 原文地址:https://www.cnblogs.com/KevinGeorge/p/7866885.html
Copyright © 2020-2023  润新知