知识体系结构应用程序:是一段可以执行的代码,由操作系统管理。
编译原理,链接器,装载器:是对操作系统依赖的一个工具,将用户的代码变成可执行的机器码,编译器仅仅检查和翻译用户的语言逻辑,但并不装配成符合操作系统要求的可执行文件格式,如windows要求的EXE文件为PE格式(EXE文件并不仅仅是一个可执行的代码段,而且包含了很多其他的内容,如数据段)。
操作系统接口API:是一个可以被用户程序调用的系统功能接口,可以说,我们编写程序,除了计算和流程控制这些只需要用到CPU指令和CPU寄存器的代码外,其余要访问其他(硬件)资源(包括内存,外设)的代码,均是通过调用OS的API来操作除CPU外的资源的,如向屏幕写一个字母,对于程序来说简单得很,print(“A”); 但是其编译后执行的过程是复杂的,编译后的程序会调用操作系统的API,将当前应用程序的状态(上下文,如光标的位置)以及字母传递给显示器的驱动程序去显示。
操作系统管理与调度:操作系统要实现一般通用的资源管理,也要实现资源使用的协调,包含CPU,内存,磁盘,外设。
首先要确定为什么需要操作系统,操作系统设计的目标是什么?1.我们总是不能等做完一件事情才去做另外一件,因为有些事情做的过程需要等待,有时候也需要暂停一下当前的任务,先去处理更急的事情,等我回来时又需要以前的任务保持当时的状态,所以需要计算机也要具备这样的能力,那怎么实现呢?2.CPU和内存是计算机的最需要的资源,就如我们的人脑一样,一般很难在同一时间做两件事情。
需要处理好一件事情再处理另一件,如果处理得越快就越好,但是不能前一件事情要等待,你就休息了,后面一件也做不了,计算机的办法就是你不用CPU了,那好你等待下,我先处理下一个事情。
3.我们写程序,不可能对每个应用,我们重新去写那些驱动程序,也不可能按照自己的想法去处理这些通常的资源管理。
否则很多人各自写的应用软件就没法在一个电脑上运行。
操作系统目标:1.实现代码重用,对于硬件的访问,对于CPU和内存的充分利用,使不同的应用不需要重新去写这些代码。
2.实现各个任务(不同应用程序)的协调使用,使用户可以实现暂停、重新启用某个任务。
3.实现数据的安全管理,实现良好的人机界面的管理。
4.实现一个开放的体系结构,提供系统调用使用户可以快速编写自己的应用,并提供编译器、链接器、装载器来让用户编写的程序变成可以与操作系统接口的可执行软件。
操作系统的功能分层:CPU管理是操作系统的核心:操作系统与用户程序其实可以看成是一个程序,与以前的单任务系统和单片机程序没有本质的区别。
我们来看整个PC机运行过程:1.系统上电。
2.主板上CPU的CS值设置为0Fx000,IP值设置为0xFFF0,这样CS:IP就指向0xFFFF0位置,这个是程序的开始地址,而硬件上在总线上挂接在0xFFFF0地址的是主板的BIOS芯片,BIOS开始运行,BIOS是Basic Input Output System简写,意思即基本的输入输出系统,如果学过单片机就很好理解,其实就是一个程序,由主板设计的公司的程序员编写的,通过一定的方法(如编程器)写入到芯片内,这段程序会一上电就开始运行。
3.BIOS会检查所有的主板资源,并初始化主板的硬件资源,如总线控制器、显示卡、内存等,并将主板的固有资源和接插件的信息放入固定的内存区域,以便操作系统可以从中获取得到当前的主板上有些什么设备资源。
4.BIOS会在内存地址的最低位0x000000构建起中断向量表,共1K内存(一个向量CS:IP各两个字节,共256个向量),接着是1/4K(256byte)的内存放BIOS数据,接下来在0x0E2CE(56K处)加载了8K左右的与中断向量表相应的若干中断服务程序。
5.当BIOS程序检测到主板上的设备符合启动系统的条件,就读取硬磁盘的引导扇区(第一扇区,这里也是一个程序,从哪个磁盘加载由CMOS设置确定),BIOS 系统将这段程序bootloader读入内存,并将控制权交给引导程序。
6.BIOS具有驱动硬盘等硬件的驱动程序,并且,具有基本的硬件驱动服务程序。
这些都由主板硬件厂商提供。
Bootloader会调用BIOS的驱动程序和已有的中断服务来从硬盘读取操作系统的核心到内存,并将CPU控制交给操作系统。
(操作系统就如一段数据被映射到内存,然后程序通过修改CS:IP跳转到操作系统的入口。
)7.操作系统会通过IGDT重新构建中断向量表。
每个硬件产生的中断,其编号在硬件设计之初就已经设计好,外部硬件中断/CPU内部异常中断/程序调用中断,其中断号和程序是预先设置好的,当有外部中断时,中断寄存器IPR会暂时存储,并与中断屏蔽寄存器IMR进行AND位运算,然后就可以确定是否处理当前中断,这个是硬件电路实现的,运算后的结果经过中断处理(中断译码)进入CPU的中断寄存器IDTR,CPU执行完当前指令,会自动处理(检查)中断,并将CS:IP指向中断地址,这个地址是什么呢?在实模式下(16位模式),中断译码根据中断号N x 4(每个中断4个字节)直接设置IP,也就是中断的程序地址没法更改的,然后在中断向量的位置就是一个跳转指令,跳转到服务程序处。
在保护模式下呢,中断向量的原理与组织与实模式基本一样,也是256个中断处理程序,但是其中断服务程序不在固定的位置,中断向量表也不在固定的位置,CPU的IDTR寄存器由操作系统在系统初始化之初就装入了中断向量表(中断门表)在内存中的寻址位置信息,保护模式下,硬件将IDTR和中断号N译码找到中断表的该中断描述项,而描述项说这个服务程序在GDT或LDT表中的第X项描述的段中,以及偏移多少可以找到程序,然后找到这个段的基址+32位的地址偏移量。
8.操作系统从实模式转保护模式时,最重要的一个是构建内存映射表和各种描述符表。
CPU访问内存时,是通过MMU进行了译码的,MMU的作用就是把CPU指令中的虚拟地址(是程序员编写的地址,一般高级语言编写的程序不直接写地址,但是程序装载到内存后,所有访问地址的指令都发生了地址修改,这是由装载器设置的。
)变成实际的物理地址。
9.操作系统为什么需要MMU,计算机从主板启动后,是在ROM中运行的,速度相对于RAM来说是非常慢,我们就想到把程序复制到RAM中运行,但是计算机体系的执行是有固定的地址的,如CPU上电首先从0xFFFF0地址加载第一条指令,发生错误则会自动将IP指向0x0000开始的中断向量表,如果我们将程序COPY 到RAM运行,但是硬件一中断,还是会跑到硬件地址的0x0000处的向量表去运行,还是在ROM中,一样缓慢,为了解决这个问题,我们想到了地址转换,当将程序COPY到RAM中后,构建MMU的页表,然后启动MMU的地址转换功能,然后程序开始从我们设定的地址开始运行(如0xFFFA0),而CPU也为了与操作系统配合,也定义了保护模式,其运行规则也相应发生了变化,其IGTR中的值由实模式时的0x000变成了由操作系统定义的中断门表的地址。
保护模式时的中断程序的寻址比实模式复杂,因其中断处理器硬件也复杂。
而对于BIOS的ROM访问地址,也被映射到了新的虚拟地址空间,不再是0xFFFF0,所以对于ROM中的中断程序的访问,是通过IGTR+中断描述项定位到该内存地址。
所有的外设的内存映射地址均被操作系统重新映射和管理。
(系统上电时,处理器的程序指针从0x0(或者是由0Xffff_0000处高端启动)处启动,顺序执行程序,在程序指针(PC)启动地址,属于非易失性存储器空间范围,如ROM、FLASH等。
然而与上百兆的嵌入式处理器相比,FLASH、ROM 等存储器响应速度慢,已成为提高系统性能的一个瓶颈。
而SDRAM具有很高的响应速度,为何不使用SDRAM来执行程序呢?为了提高系统整体速度,可以这样设想,利用FLASH、ROM对系统进行配置,把真正的应用程序下载到SDRAM 中运行,这样就可以提高系统的性能。
然而这种想法又遇到了另外一个问题,当ARM处理器响应异常事件时,程序指针将要跳转到一个确定的位置,假设发生了IRQ中断,PC将指向0x18(如果为高端启动,则相应指向0vxffff_0018处),而此时0x18处仍为非易失性存储器所占据的位置,则程序的执行还是有一部分要在FLASH或者ROM中来执行的。
那么我们可不可以使程序完全都SDRAM中运行那?答案是肯定的,这就引入了MMU,利用MMU,可把SDRAM的地址完全映射到0x0起始的一片连续地址空间,而把原来占据这片空间的FLASH或者ROM 映射到其它不相冲突的存储空间位置。
例如,FLASH的地址从0x0000_0000-0x00ff_ffff,而SDRAM的地址范围是0x3000_0000-0x31ff_ffff,则可把SDRAM 地址映射为0x0000_0000-0x1fff_ffff而FLASH的地址可以映射到0x9000_0000-0x90ff_ffff(此处地址空间为空闲,未被占用)。
映射完成后,如果处理器发生异常,假设依然为IRQ中断,PC指针指向0x18处的地址,而这个时候PC实际上是从位于物理地址的0x3000_0018处读取指令。
通过MMU的映射,则可实现程序完全运行在SDRAM之中)10.内存映射表:是为MMU构建的一块内存区域,其内容为一个表,或者叫一个数组,每个元素标记了[虚拟地址:物理地址],页表一般分两极,第一级为1M一个项,第二级则是1M内的索引。
那会有多少呢,4G=4K项,然后每个1M=256项,所以页表大小为1M,如果每个项为32bit,那么至少需要256K个指令周期才能把内存的页表装入MMU,也就是0.4ms, windows的CPU分时片为20ms。
那么进程切换的时间不少于1ms。
11.CPU中有是否启用MMU的寄存器设置,如果不启用,则CPU发出读写地址线信号,同时MMU不会做出反应,使能信号直接被MMU输出,RAM检测到指令,直接将数据放到总线上,并通知CPU数据准备好。
如果启用MMU,CPU发出读写指令,MMU同时从总线获取地址数据经过硬件运算,仅仅一个硬件周期,然后修改总线的地址,并通知内存或北桥芯片地址准备好。
12.对于操作系统来说,只要构建每个进程的内存映射表,并在进程切换时将内存映射表复制到MMU的缓冲中。
13.而对于应用程序来说,是不能操作MMU的,所以,当企图访问没有映射的虚拟内存时,MMU会向CPU会产生缺页中断,然后在中断服务程序中,操作系统会根据是否是被换出内存还是没有初始化,来决定是从硬盘装载内存,或抛出异常错误。
14.操作系统的内存管理,是分段式管理,并在内存中构建了一个段描述符表,这个表是用来告诉大家(CPU,所有程序)每个段内放了什么东西,是可执行代码,或是数据,或者是一个只读存储器,或者这个部分是不能访问的。