一、操作系统如何加载
1、读入内存
计算机的运转其实就是不断的进行“取指-执行”的这个过程,而取指就是从内存中取指。大家都知道,我们在装系统的时候会把操作系统装在磁盘里。既然要启动操作系统,那么要做的第一步自然就是把存在磁盘中的操作系统读入内存的指定位置中。
计算机硬件厂商在只读存储器 ROM (ROM的特点是一次写入反复读取,RAM 断电后存的数据就没了)中开辟了一块空间,这段空间被称为 BIOS(basic input/output system)。BIOS 中放置的代码是对基本硬件的测试代码,以及一些让用户调用硬件基本输入输出功能的子程序。
计算机加电后最先做的事就是要把寻址的 PC (程序计数器)指向存放 BIOS 的地方。
计算机硬件厂商在只读存储器 ROM (ROM的特点是一次写入反复读取,RAM 断电后存的数据就没了中开辟了一块空间,这段空间被称为 BIOS(basic input/output system)。BIOS大家应该都见过,但具体的功能可能说不清,其实 BIOS 中放置的代码是对 基本硬件的测试代码,以及一些让用户调用硬件基本输入输出功能的子程序。计算机加电后最先做的事就是要把寻址的 PC (程序计数器)指向存放 BIOS 的地方。BIOS 主要能干两件事;(1)检测硬件。如果硬件有问题,大家看到计算机就卡在初始页面了,大家可能也有过计算机硬盘损坏然后卡在开机界面的经历;(2)BIOS 提供中断功能。大家要明确,BIOS的输入输出功能也是以中断调用形式提供给用户的,在第三阶段操作系统接管中断以前,都是用的BIOS中断。通过第一步,如果BIOS检测硬件正常,就利用BIOS的中断将启动磁盘上启动扇区中的内容读入到内存中。
- 启动扇区中的内容就是文件 bootsect.s(是一个汇编文件)
- bootsect.s 中的代码主要做了三件事:
2.1 把 setup.s 文件读到内存的指定位置。第二阶段启动保护模式就要靠 setup.s 这个文件。
2.2 显示系统标识。操作系统打出自己的logo
2.3 把 system(进程模块、内存模块、设备驱动等)读到系统的指定位置
C 程序经过(编译环境是变量)编译后好多细节都是不可控的,所以要用汇编来严格控制。
2、切换保护模式
把该读入的文件读入后,要为系统初始化做准备了。那么就要开始执行读入的 setup.s 文件了。setup.s 文件主要做了两件事:
- 获取硬件参数(比如内存和硬盘大小等等)
- 将实模式切换为保护模式。
为什么要从实模式切换成保护模式?
(1)实模式的寻址方式为段基址左移四位加偏移,内存寻址范围只在 1M 以内。而切换成保护模式后,32位机的寻址范围就内达到4G(大家可能也听说过32位系统不适配4G以上的内存。
(2)另外一个原因是实模式对于内存的访问不会有任何保护,谁来了也能访问,而保护模式可以对内存的访问进行一定的限制。这对操作系统来说很重要,如果操作系统不能保护内存,使得每个进程都能直接对任意内存进行访问,并发时会出大问题。
3、启动段页
操作系统进入32位的保护模式后,紧接着要执行一段名为 head.s 的代码
- 设置中断表。
操作系统中是把 CPU 对系统发生某个事件做出反应的行为都叫做中断。
比如敲击键盘后,系统做出响应,这种就叫 I/O 中断;刚才第一阶段时 BIOS 的输入输出功能也是一种中断;不同的操作系统遇到不同中断反应是有差别的,所以操作系统是必须要接管中断的,设置中断表。
- 设置 GDT 表
GDT 表是切换到保护模式后要用到的,GDT(Global Descriptor Table)表也叫全局描述表,是一个很重要的数据结构。对于保护模式下的寻址以及控制权限很重要。
- 设置页表
4、系统初始化
开始逐步执行初始化操作:
- mem_init(memory_start, memory_end) 初始化内存。系统内核 system 分配到 0~1 MB,磁盘高速缓存分配在 1- 4MB,所以 memory_start 是4 MB,mem_init()就是为了初始化 4MB 以后的内存空间。
- hd_init() 初始化硬盘。
- sti() 这个和系统调用相关。
- move_to_user_mode() 切换用户态