操作系统启动流程

目录

什么是操作系统

操作系统的组成

计算工作原理

图灵机

操作系统启动过程--第一阶段

bootsect.s阶段    

Makefile

操作系统过程---第二阶段

setup阶段

初始化参数

启动保护模式

操作系统启动过程-----第三阶段

system阶段

操作系统启动过程----第四阶段

main.c阶段


什么是操作系统

操作系统实际是用来操作硬件资源提供给上层应用使用的一种“特殊软件”

操作系统的组成

计算硬件主要组成:CPU ,内存,各种输入输出IO设备(显示器,键盘,鼠标,磁盘,网络等外设)

操作系统管理CPU-----抽象出进程,即CPU的管理变成进程的管理

操作系统管理外设-----抽象出文件,即磁盘管理变成文件管理

一个操作系统包括四个基本管理模块:进程管理,内存管理,I/O管理以及文件系统,给上层应用提供的系统接口

计算工作原理

图灵机

计算机最基本的东西是一个计算模型--图灵机

参考人类计算过程,图灵机开始工作后:例如要计算f(s)

  1. 在纸带用编码写下2

  2. 移动“读指针”将3读到控制器中

  3. 控制器中有一套控制电路对应这个映射,控制电路开始运转,计算出f(3) = -3,

  4. 控制器将结果 -3写到纸带上。

从图灵机的原理上我们可以看到真实计算机的工作原理就是  取指----执行,再取指---执行,循环操作的一个场景, 这是操作系统中无数次出现的基本场景  取指---执行

操作系统启动过程--第一阶段

bootsect.s阶段    

在按下开机键后,电源接通,计算机加电,在开机启动的时候,计算机首先工作在实模式(16位寻址模式),硬件电路会初始化设置PC寄存器的值。(程序计数器 Program Counter,即程序指令的要执行位置, 是一种通用寄存器,但是有特殊用途,用来指向当前运行指令的下一条指令),如IBM的硬件电路将这个PC寄存器的初始值设置为0xFFFF0 地址,  将这个地址放到地址总线上去,以取出内存中存放的指令,即0xFFFF0 地址处取出第一条指令开始执行。

    那么内存地址 0xFFFF0 上取出的指令是什么?先来了解下RAM和ROM的概念

内存是随机存储器(random access messory, RAM),属于易失性存储器,故未加电时RAM中没有存放任何内容,因此一上电时RAM中没有任何信息的。

为了设置一个起点,计算机硬件厂商在只读存储器(read-only memory , ROM)中开辟一块空间,IBM 的0xFFFF0 就指向这个区域,这段ROM就被称为BIOS(basic input/output system,基本输入输出系统),BIOS里面放了对基本硬件的测试代码,如对主板,内存等硬件的测试,同时还提供一些让用户调用硬件基本输入输出功能的子程序,如int 0x10(BIOS中断)

CPU从0xFFFF0 指向 的这段ROM中取出的指令要成的工作是测试各种硬件是否正常,如果出现异常则停止启动(如SSD坏了啦,电脑就会卡那不动或者反复重启),如果检测正常,则利用BIOS的输入功能将启动磁盘上启动扇区中的内容读到内存0x7C00的地址处(疑问:这里的内存是指RAM吗?),并设置PC寄存器的地址为0x7C00

    因为PC中的地址已经设置为0x7C00, 接下来就要到该内存地址下执行指令了,该地址下放的是刚才读取的启动扇区的内容(就是启动磁盘上的0号柱面,0号磁头,1号扇区,共512个字节),操作系统第一个要编写的文件就是这个引导扇区中存放的程序代码,通常将其命名为bootsect.s(是一个汇编文件)

bootsect.s这个文件中相关代码做的事情如下:

  1. 将内存0x7C00处的512个字节(正好就是bootsect.s的全部程序)移动到内存地址0x90000开始的一段内存中,这样移动的作用是为读入操作系统核心代码腾出空间

  2. 调用int 0x13中断(BIOS中断,这是一个读写磁盘的中断),该中断会调用后的代码用来从磁盘上读入操作系统的setup.s文件到内存中, 读取内容是将0号驱动器中从0号柱面,0号磁头,2号扇区开始的4个扇区的内容读入到内存中,此处是0x90200,正好移动到bootsect.sh的后面。磁盘上这4个扇区中的内容就是操作系统的一个文件,通常称为setup.s

  3. 开机启动过程中打印LOGO也是在bootsect.s执行的阶段,在该阶段通过BIOS中断in0x10(该中断的作用是在屏幕上输出信息), 经过一系列寄存器的设置,会取出光标所在的位置,为后面显示纤细做准备
    即LOGO信息的配置是在这里

  4. 接下来就需要从磁盘上读取操作系统的主体部分
    在读取主体部分之前,需要先获取一些磁盘参数,比如每个磁盘的扇区个数(通过BIOS 的0x13中断, 该中断调用后能获取每个刺刀的扇区个数)
    设置寄存器地址为0x10000,这个内存地址用来存放从磁盘读出的内容, 该地址是操作系统主体代码在内存中开始的位置(这也是上面bootsect.s一开始的代码移动,即从0x7C00移动到0x90000处的原因,就是为了读入操作系统的主体代码准备的)
    上述准备就绪后,开始真正读取系统模块,用一个循环一实现一个磁道一个磁道的读入,同时修改制定寄存器的地址,直达系统模块被全部读入到内存中)
    bootsect.s占用1个扇区,setup.s占用4个扇区,故system模块从第6个扇区开始读

第一阶段启动过程小结

  1. BIOS读取操作系统的第1号扇区bootsect.s文件,然后执行bootsect.s文件中程序

  2. bootsect.s继续读取操作系统的setup.s文件,将来执行权会交给setup.s文件,setup.sh会完成一些操作系统设置工作

  3. 接下里bootsect.s还要读入操作系统的主体模板system,setup.s执行完成后,会执行system

bootsect.s 完成的工作:

  1. 将磁盘上从第二到第五这4个扇区构成的setup的模块读入到内存的0x90200处

  2. 在显示器上输出操作系统的logo标识

  3. 从磁盘的第6个扇区开始读取长度为SYSSIZE长度的操作系统的system模块, 并将其放在内存的0x10000处

想让bootsec工作流程正确,磁盘上的第一个扇区必须防止bootsect.s编译后的结果,第二个到第五个的四个扇区必须放置setup.s编译后的结果,第六个扇区开始放置编译后的system的模块。即启动磁盘上的模块分布必须严格按照如下:

Makefile

为了使操作系统源码文件最后的形式如上图所示,即将操作系统源码编译链接后形成一个二进制文件,也就是著名的操作系统镜像(mirror)文件, 需要使用Makefile,将不同的汇编文件,C文件, H文件组织到不同的目录下,控制这些文件的编译来形成一个特定格式的镜像文件

格式如下:

目标:该目标依赖的其他目标
          产生该目录要执行的命令

操作系统过程---第二阶段

setup阶段

在引导扇区代码bootsect.s的工作:读入setup ,显示logo, 读入system完成以后,接下来操作系统应该为系统初始化做准备, 即执行setup(也就是执行setup.s中的程序)

因为bootsect.s除了要读取setup 还要读入system模块,所有需要在读完SYSSIZE长度的system模块的内容后PC指针跳转到0x90200的内存地址,找到setup.s的开始位置开始执行(取指---执行的动作)

setup阶段的工作如下:

  1. 初始化必备的一些基本参数需要setup阶段获取(如内存有多大,磁盘有多大等)

  2. 将来的操作系统要工作的保护模式下(32位),目前是工作在实模式(16位),因为32位的寻址更多,故要在这里启动保护模式

初始化参数

调用BIOS中断0x15, 获取扩展内存的大小, 单位是KB, 将内存大下的值放在内存地址0x90000处,将来系统初始化时可以读取这个值来初始化内存管理
调用BIOS中断0x41 获取硬盘信息,该中断与其他中断有一定区别,如int 0x10中断在执行时,会根据中断号到中断向量表(该表存放在内存的0地址处)中特定位置取出中断处理地址的入口地址,但中断向量表0x41表项存储的却不是中断处理程序的入口地址,而是一个硬盘的基本参数共16B,表示磁盘包含多少个柱面,多少个磁头,每个磁道多少个扇区的信息

还有其他信息如显示器信息等, 获取方式类似

在获取硬件的基本参数后,setup的下一项核心工作是启动保护模式

启动保护模式

保护模式,即32位模式,与实模式(16位模)不同的是寻址方式不同(目前还不知道原理),开启32位寻址方式后,计算机要启动另一套电路啦解释要执行的指令,即计算PC指针的位置?

计算机寻址方式中需要用到两个重要信息,一个是地址表,通常这个表被称为GDT表(global descriptor table,GDT 全局描述符表), 另一个是如何让计算机硬件找到这个表,因为整个寻址过程是自动化的。

setup.s会完成GDT表的构建以及初始化工作,另外,这个表的起始地址会被存放到一个被称为GDTR的寄存器中。

GDT表有三个表项: 表项0表示没有用,表项1表示操作系统内核代码段,表项2表示操作系统内核数据段。

setup.s 在保护模式启动后,取出来的一条指令是jmpi 0, 8之前,还会将整个system模块拖拽到0x地址处(即将内存地址0x10000~0X90000间的全部内容移动到地址0x00000~0x80000地址处)。

jmpi跳转的位置即head.s的第一句指令,然后就进入操作系统启动的第三阶段

操作系统启动过程-----第三阶段

system阶段

进入32位保护模式以后要执行的一段代码是head.s。bootsect将操作系统读入内存,setup读取一些硬件参数并启动保护模式,我们就可以对操作系统管理的资源的关键数据结构进行初始化。但是初始化之前还有一些准备工作要做:

  1. 设置中断表
    因为从现在开始操作系统不再使用BIOS中断了,实际上将system从0x10000挪到0x0地址处时已经无法使用BIOS中断了,因为BIOS中断向量表放置在0地址处,另外,接管中断是操作系统必须要做的事情,因为不同的操作系统遇到同一中断所实施的操作不同

  2. 设置GDT表
    虽然上面setup中设置了GDT表,但那时为了jmpi 0, 8寻址临时建立的,现在进入system模块,需要重新建立
    heade.s中设置IDT(中断描述符表)表和GDT表与在setup.s中类似,即设计两个连续8B的内存数组,每个数组项占8B,分别作为中断描述表(interrupt   descriptor table )和GDT表
    GDT表的初始位置发生了变化,并且更长,为局部描述符表 local descriptor table LDT 预留空间

  3. 设置页表
    进入32位模式后寻址方式更加复杂,即GDT[CS] + EIP算出来的地址仍然不能直接输出到地址总线上,通常还需要用这个地址再去查一次页表才能得到真正的“物理地址” 并输出到地址总线
    设置页表是在设置GDT表完成之后,在页表设置完成后,通过页表映射得到的物理地址就等于输入的地址, 即PageTable
    对于操作系统的system模块而言,程序中使用的偏移地址和实际输出到物理内存上物理地址实际是一样的,但尽管两个地址一样,每次取出指令,执行指令涉及内存中的操作数时,都要完成整个地址的映射过程(为什么?)
    head.s代码建立这个页表的核心工作主要包括:填写5个长度为4KB的页表,设置页表寄存器CR3,以及启动页表电路 三个部分

实际上,操作系统启动涉及的所有工作都是为了形成如下的内存图,执行到这里,这张内存图已经有了,操作系统的准备工作完成,操作系统接下来就可以初始化,head.s最后一段代码是负责跳转到操作系统的初始化代码处。初始化主要包括:初始化一些数据结构(数组,链表等, 通常用C语言)

head.s最后一段代码是完成从汇编语言跳转到C程序的代码 L6: jmp L6, 为了保证main()函数正确返回,需要在跳到main()之前在栈中压入main()返回的要执行的指令的地址,而操作系统启动以后不需要返回,因此此处压入标号L6,在main()函数返回以后跳翻到L6执行,这是一个死循环,所有main是一个永远都不能退出的函数,否则计算机就要“死机”

这里就开始进入操作系统启动的第四阶段了

操作系统启动过程----第四阶段

main.c阶段

一切准备就绪,操作系统终于可以初始化并开始运转,C语言的main()函数主要功能就是初始化各种管理软硬件资源的数据结构,通过调用各种初始化函数来完成相应的初始化工作,比如调用mem_init()来初始化内存,调用hd_init()来初始化硬盘,其他类似调用对应的*_init()函数。

内存初始化

通过调用mem_init()函数,该函数有两个参数,分别表示要管理的起始内存地址和结束内存地址,起始地址为4M,因为0~-1MB分配给了系统内核system, 1M币~4MB将分配给磁盘告诉缓存,所以4MB以后的才是给用户应用程序可用的。结束地址由0x90000处的取出的内容决定(为什么?)

在管理时要需要取整为4KB的整数倍,因为操作系统要按照页来管理内存,这里操作系统的一页的大小及时4KB(不足1页的丢弃)

在关键行的各种数据结构初始化完成后,操作系统开始运转

main()函数中最后关键四句代码开始运转操作系统

void main(void)

{

......

sti();

move_to_user_mode();

if(!fork()) {init();}

for(;;){pause();}

}

前两条和系统接口相关,第三条和进程有关, 第四条和线程,调度有关,到此,操作系统终于启动,main()函数代码中的init()会启动一个shell。

操作系统启动的主要工作就三项:

  1. 系统准备:读入内核,启动保护模式,启动段页

  2. 系统初始化

  3. 系统运转进入shell

如图

  • 9
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值