目录
1 操作系统的基本概述
1.1 操作系统的概念
- 操作系统是系统资源的管理者:资源有硬件、软件。
- 操作系统也为上层的用户以及应用程序提供了方便的接口以及环境。
- 操作系统是软件而不是硬件,是最接近硬件的软件。
操作系统中对于软件以及硬件的管控可以看如下示例图,可以通过任务管理器来明确:
1.2 操作系统的功能
1.2.1 操作系统提供的功能及示例
操作系统提供的功能:
- 处理机管理
- 存储器管理
- 文件管理
- 设备管理
用了上述四个功能的实际例子:用QQ和朋友视频聊天的过程
- step1:在各个文件夹中找到QQ安装的位置(如D:/Tencent/QQ/Bin)文件管理
- step2:双击打开QQ.exe(需要把该程序相关数据放入内存)。存储器管理
- step3:正常运行,会被处理机(CPU)进行处理。处理机管理
- step4:视频聊天会将摄像头设备分配给QQ来进行使用,设备管理
1.2.2 操作系统提供的方便易用服务
1.2.2.1 GUI用户界面、命令接口
①GUI(图形化用户界面):只需要通过一些操作来直接替代很多的代码指令
而对于早期的操作系统则是通过命令接口方式与操作系统交互
②命令接口分为两种:联机命令接口和脱机命令接口
1、联机命令接口(也称交互式命令接口)
特点:用户发送一条指令,操作系统跟着执行一条指令。用户与操作系统不断地进行交互
2、脱机命令接口(批处理命令接口)
特点:将一系列的命令罗列在了一个xx.bat文件,用户提出一堆指令,操作系统跟着做一堆。
1.2.2.2 给程序员提供的程序接口
程序接口:可以在程序中通过使用系统调用的方式来使用程序接口,普通用户不能够直接使用程序接口,只能够通过程序代码间接使用。
实际应用举例:通过编写C语言代码在屏幕上输出"Hello World",实际在printf函数的底层就使用到了操作系统提供的显式相关的"系统调用"。
- 操作系统的接口函数是连接应用软件与操作系统的中间桥梁。系统调用是操作系统提供给应用程序的接口函数,应用程序可以通过这些接口函数来让操作系统执行相关的操作,从而获得操作系统的服务
下图中用户能够与操作系统中有相连的部分的原因就是:用户可以通过使用GUI和编写程序接口来和操作系统进行交互,而对于应用程序则是通过系统调用方式来与操作系统之间进行交互。
1.2.2.3 总结
1.3 操作系统对硬件机器的扩展
1.3.1 并发
并发:指两个或多个事件在同一时间间隔内发生,这些事件在宏观上来看是同时发生的,但在微观上是交替发生的。
并行:指两个或多个时间在同一个时刻同时发生
重要考点:
- 单核CPU可以同一时刻只能执行一个程序,各个程序只能并发的执行。
- 多核CPU同一时刻可以同时执行多个程序,多个程序可以并发的执行。
1.3.2 共享
共享指的是资源共享,对于系统中的资源可供内存中多个并发执行的进程共同使用。
两种资源共享方式:
- 互斥共享方式:系统中某些资源,可以提供给多个进程使用,一个时间段只允许一个进程访问资源。
- 同时共享方式:系统中某些资源,允许在一个时间由多个进程"同时"对它们进行访问。
注意:这里的"同时"一般是宏观上的,对于在微观上,实际上多个进程在对同一个资源进行交替的访问
实际例子:
- 互斥共享例子:QQ和微信视频,在同一时间只能够分配给一个进程使用。
- 同时共享例子:使用QQ与微信发送同一个文件,在宏观上可以感觉到对于两个文件都在访问硬盘资源,从中读取数据,实际在微观中,两个进程是交替访问硬盘的。
并发性与共享性是互为存在条件的
如果失去并发性,那么系统中只能有一个程序在运行,此时共享性就失去了存在的意义。
如果失去共享性,那么QQ与微信就不能够同时访问硬盘资源,那么即使能够进行并发也失去了意义。
1.3.3 虚拟
虚拟:指的是把一个物理上的实体变为若干个逻辑上的对应物,物理实体是实际存在的,而逻辑上对应物则是用户感受到的。
- 例如虚拟机中我们可以构建多个虚拟机然后安装多个操作系统,即可进行使用
虚拟技术主要分为:空分复用技术(虚拟存储器技术)、时分复用技术(虚拟处理器)。
- 针对时分复用技术而言:如果失去了并发性,那么时间段内系统中只能处理一道程序,此时就失去了实现虚拟性的意义了,因此,没有并发性就谈不上虚拟性。
下面是(虚拟存储器技术-空分复用技术)的示例:
下面(虚拟处理器器-时分复用技术):
虚拟处理器-时分复用技术:微观上处理机在各个微小的时间段内交替着为各个进程服务。
- 简述:将大的时间段分为很小的时间片
注意:核就是CPU
1.3.4 异步
异步:在多道程序环境下,允许多个程序并发执行,但由于资源有限,进程的执行并不是一贯到底的,而是走走停停,以不可预知的速度向前推进,这就是进程的异步性。
- 走走停停是指:在并发的过程中,如果有互斥型的资源两个进程都想要使用,那么其中一个没有获得资源的进程就需要阻塞等待,所以说这个异步并不是能够像同步一样不断地向下执行
1.3.5 并发、共享、虚拟、异步的关系
并发与共享关系:并发性与共享性是互为存在条件的,若一方不存在,另一方存在也无意义了。
并发与虚拟关系:如果没有并发,虚拟性也没有意义了。
并发与异步的关系:只有系统拥有并发性,才能能够有异步性。如果同步执行某一段程序,则不会发生资源使用冲突的情况,也就不会产生异步性。
2 操作系统的发展与分类
2.1 手工操作阶段
这个阶段并没有出现操作系统。
该阶段执行流程:
- 程序将代码是提前写在了纸带机上
- 将它放入计算机
- 计算机读取指令执行得到结果后输出到纸带机上
- 程序员通过手工方式取走。
在这个阶段的机器造价极其昂贵,通过这种手动输入输出的方式,浪费了大量计算机的资源利用率,下图是整个过程中占用的时间开销,可以看到计算机处理占到了很小的一块:
2.2 单道批处理阶段
解决手动操作系统十分低效的问题,出现了单道批处理系统。
单道批处理系统:引入脱机输入/输出技术(外围机+磁带完成),并由监督程序负责控制作业的输入、输出。
该阶段执行流程:
- 程序员可以将多道程序放在指定机器上,
- 外围机会控制着这些纸带机提前存储到磁带中
- 计算机从磁带中依次读取输入的作业并执行(一个作业执行完执行下一条作业)
- 计算机将程序的运行结果输出到磁带中
如下图所示,可以看到在这一个阶段中,对于输入、输出的时间降低很多,缓解了人机速度矛盾。
优点:输入输出的时间大量降低,缓解了一定程序的人机速度矛盾,资源利用率有所提升。
缺点:内存仅有一道程序运行,只有该程序运行结束并输出后才能够调入下一条程序,CPU依然有大量时间是在空闲等待I/O完成,资源利用率依旧还是很低。
2.3 多道批处理阶段
多道批处理系统:每次读入多道程序,让这些程序进行并发的执行。
实际作业的执行过程:在当前阶段里,可以读入多道程序并且可以并发(宏观上并行, 微观上串行)执行处理任务:
第一个作业实际是由①②④组成,第二个作业是③⑤⑦组成,第三个作业是⑥⑧⑨组成
优点:多道程序并发执行,可以共享计算机资源,资源利用率得到了大幅度提高,CPU和其他资源能够保持"忙碌"状态,系统的吞吐量增大。
缺点:用户响应时间长,没有人机交互的功能(用户提交自己的作业就只能等待计算机处理完成,中间不能够控制作业的执行),并且无法调试程序以及无法在程序运行时输入一些参数。
2.4 分时操作系统
为了解决没有人机交互的问题,发明了分时操作系统。
分时操作系统:计算机以时间片尾单位轮流的给各个用户/作业服务,各个用户可以通过终端与计算机进行交互,如下:
通过分时操作系统能够使用户的一些输入等其他操作能够及时的被CPU响应到,解决了人机交互的问题。
优点:用户请求可以被及时响应,解决了人机交互问题,能够允许多个用户同时使用一台计算机,并且用户对计算机的操作能够相互独立,感觉不到其他用户也在同时使用。
缺点:不能够优先的处理一些紧急的任务,因为在这个阶段操作系统对于每个用户/作业都是公平的,循环的为每个用户/作业服务一个时间片,不区分任务的紧急性。
2.5 实时操作系统
实时操作系统:在实时操作系统的控制下,计算机系统接收到外部信号及时的进行处理,并且在严格的时限内处理完事件。
分为两类:硬实时操作系统和软实时系统
优点:能够优先相应一些紧急任务,某些紧急任务不需时间片排队。
特点:及时性和可靠性。
2.6 其他几种操作系统
3 操作系统运行环境
3.1 操作系统的运行机制
3.1.1 预备知识
对于下面黑框中的"指令"实际上就是交互式命令接口,在这里指令应当是上面机器语言的二进制代码:
3.1.2 程序和指令
应用程序:普通程序员写的,跑在操作系统之上的。
内核程序:微软、苹果的顶级大佬写的操作系统的代码就是内核程序。在内核中包含的只是操作系统中最重要、最核心,最必不可少的这些功能。
- 内核:许多内核程序组成了操作系统内核,简称"内核"。内核是操作系统中最重要最核心的部分,也是最接近硬件的部分。
- 可以说一个操作系统只要有内核就够了,例如Docker中只要有Linux内核就可以了
注意:操作系统的功能未必都在内核中,例如图形化用户界面,即使没有图形化用户界面,依旧能够使用类似于CMD命令窗口来使用操作系统。
针对于内核以及应用程序是否可以使用任一指令?
- 针对于一些"特权指令",例如内存清零指令,这些指令都影响十分大,只允许"管理者"也就是操作系统的内核来使用。(在CPU设计和生产的时候就划分了特权指令和非特权指令,因此CPU执行一条指令就能够判断出类型)
- 应用程序只能够使用"非特权指令",例如加法指令、减法指令等等。
3.1.3 分辨内核程序和应用程序
分辨内核程序和应用程序
- 处于内核态时,说明此时正在运行的是内核程序,此时可以执行特权指令。
- 处于用户态时,说明此时正在运行的是应用程序,此时只能执行非特权指令。
如何分辨CPU是处于哪个状态呢(用户态、内核态)?
- CPU中有一个寄存器叫做程序状态字寄存器(PSW),其中有一个二进制位,这个位是1表示内核态,0表示用户态。
- 别名:内核态=核心态=管态。用户态=目态。
3.1.4 内核态与用户态的切换
通过一个示例来进行说明这两者之间的切换:
- 开机,CPU当前默认为"内核态",操作系统内核程序先上CPU运行。
- 开机完成之后,用户启动某一个应用程序。
- 操作系统内核程序会在合适的时候主动去让出CPU的使用权(当前是内核态),让应用程序上CPU运行。(让出CPU使用权过程就是内核态—>用户态的过程,操作系统内核在让出CPU之前,会执行一条特权指令将PSW中的标志位设置为"用户态",此时完成切换。)
- 应用程序运行在"用户态"。
- 黑客在当前运行的应用程序中植入了一条特权指令,企图去破坏系统运行。
- 当CPU此时执行特权指令时,发现这条指令是特权指令,并且检查自己的状态为"用户态"。
- 由于用户态想要执行特权指令是非法事件,会引发一个中断信号。(CPU检测到中断信号后,此时就是用户态—>核心态的过程,对应的PSW标志位会设置为"核心态",并停止运行当前的应用程序,转而运行处理中断信号的内核程序)
- 经过"中断",操作系统会再次夺回CPU的控制权。
- 操作系统会对引发中断的事件进行处理,处理完成之后再将CPU使用权交给别的应用程序
通过这个示例,对用户态与核心态之间的转换进行梳理:
- 内核态—>用户态:处于内核态的CPU会执行内核程序中的一条特权指令(修改PSW中的标志位为用户态),这个动作意味着操作系统会主动让出CPU的使用权。
- 用户态—>内核态:处于用户态的CPU执行应用程序时,如果有特权指令会引发"中断",硬件自动完成变态过程(转变核心态),触发中断信号意味着操作系统会强行夺回CPU的使用权。
3.2 中断和异常
3.2.1 认识中断的作用
CPU会运行两种程序分别是操作系统内核程序以及应用程序。
- 操作系统内核程序:是整个系统的管理者。
作用:"中断"会使CPU从用户态变为内核态,使操作系统重新夺回对CPU的控制权。如果没有中断技术,无法实现多道程序并发。
3.2.2 中断的类型
中断的类型分为两个:内中断与外中断
- 内中断:与当前执行的指令有关,中断信号来源于CPU内部。因此中断处理结束后继续执行被中断的那一条指令
- 外中断:与当前执行的指令无关,中断信号来源于CPU外部。CPU每执行完一条指令会检测是否有外部中断,如需要处理,则处理结束后返回原程序,接着执行下一条指令
内中断例
例1:试图在用户态下执行特权指令
过程:CPU在用户态运行应用程序过程中执行了一条特权指令,此时就会触发中断信号,CPU会从用户态切换到核心态并且来执行处理中断信号的内核程序
例2:如果应用程序想要使用操作系统内核的服务,会执行一条特殊的指令—陷入指令,该指令会引发一个内部中断信号。
- 陷入指令并不是特权指令,此时这个应用程序会主动的将CPU使用权还给操作系统内核。
外中断例子
例1:时钟中断—由时钟部件发来的中断信号。
过程:
- 程序1运行在用户态,执行了50ms
- 50ms后,时钟部件会向CPU发送一个中断信号,CPU会从用户态切换到内核态执行处理时钟中断的内核程序
- 处理完成之后将CPU的使用权又交给程序2来运行,此时切回了用户态
- 等待程序2运行了50ms后,时钟部件又一次发送了中断请求,后面的处理机制与上面类似。
下图为的数字是cpu执行顺序
例2:I/O中断,由输入/输出设备发来的中断信号
过程:例如打印机在完成打印之后就会发送给CPU一个中断信号,用来表示任务已经完成,此时CPU会使用这个中断信号对应的处理I/O中断的内核程序来进行处理。
3.2.3 中断的分类
陷入:当应用程序想要去执行内核程序的服务时,就需要执行这个指令,这也是系统调用的一个原理。
故障:由错误条件引起的,并且可能被内核程序修复的问题,内核程序修复故障之后,会把CPU的使用权还给应用程序,让它继续执行下去,例如缺页故障。
终止:是由指明的错误引起的,这类错误内核程序无法修复,一般来说发生了这些类型的异常,内核程序不会将CPU使用权还给应用程序,而是会直接让这个程序终止不再运行,例如整除/0、非法使用特权指令。
注意:很多考试中,内中断一般称为异常,外中断称为中断
3.2.4 中断机制的基本原理
原理:不同的中断信号,需要用不同的中断处理程序来处理,当CPU检测到中断信号后,会根据中断信号的类型去查询"中断向量表",此时找到相应的中断处理程序在内存中的存放位置。
- 中断处理程序是内核程序,一定是运行在内核态的。
3.3 系统调用
3.3.1 系统调用的概念和作用
给用户使用的是GUI,程序接口则是一堆系统调用组成。
系统调用:是操作系统提供给应用程序(程序员/编程人员)使用的接口,可以理解为一种可供应用程序调用的特殊函数,应用程序可以通过系统调用来请求获得操作系统内核的服务
3.3.2 系统调用和库函数区别
应用程序直接调用系统调用:通过编写汇编语言代码方式直接请求。
应用程序间接调用系统调用:通过使用高级语言来编程,可以直接使用高级语言的库函数。实际这些高级语言的库函数在底层也是会使用到操作系统提供的系统调用功能请求操作系统的服务。
并不是所有的库函数都涉及到系统调用
- 不涉及系统调用的库函数:例如"取绝对值"的函数,如math.h只提供了一些计算。
- 涉及系统调用的库函数:如"创建一个新文件"的函数。
下面分别是整个机器从下层到上层可以提供的服务:
3.3.3 为什么系统调用是必须的
操作系统内核:负责协调处理各个进程请求,保证并发运行的时候不会出现类似状况
3.3.4 系统调用的功能
应用程序通过系统调用请求操作系统的服务,而系统中的各种共享资源都由操作系统内核统一掌管,因此凡是与共享资源有关的操作(如存储分配、I/O操作、文件管理等),都必须通过系统调用的方式向操作系统内核提出服务请求
好处:能够保证系统的稳定性,防止用户进行非法操作。
3.3.5 系统调用的过程
①CPU在用户态执行应用程序,程序想要发出系统调用,则需要用传参数的指令向CPU的寄存器传递一些必要的参数(例如参数1指明哪种类型的系统调用如fork系统调用,对应的参数可能有多条)。
②等待参数都放入到了寄存器中,应用程序就会执行一条特殊的指令-陷入指令。
③陷入指令执行,引发内中断。CPU检测到内部中断,确认这个中断信号是trap陷入指令引起的,CPU暂停运行,由硬件切换到内核态运行并转而去执行处理陷入指令的程序,该程序为系统调用入口程序。
④系统调用入口程序检查寄存器里的参数,通过某些参数,确定应用程序需要的类型的系统调用服务,此时操作系统去调用应用程序需要的处理程序(fork程序,此时依旧是内核态),等待执行完后,CPU转回用户态继续执行之前的应用程序。
高级语言程序完成系统调用过程进行简洁图示:
- 简洁流程:传递系统调用参数—>执行陷入指令(用户态)—>执行相应的请求程序处理系统调用(内核态)—>返回应用程序
- 别名:陷入指令=trap指令=访管指令。
3.3.4 系统调用和中断的联系
系统调用过程
- 程序想要发出系统调用,用传参数的指令向CPU的寄存器传递一些必要的参数
- 等待参数都放入到了寄存器中,应用程序执行陷入指令
- 陷入指令执行,引发内中断,由硬件将CPU的用户态转为内核态
- CPU执行系统调用入口程序,根据参数确定用户需要的系统调用服务,执行相应的系统调用服务程序
- CPU处理完成后,由硬件将CPU的内核态转为用户态,继续执行之前的程序
系统调用的目的
目的:为了使系统更稳定,安全,防止用户进行非法的越权操作
解决方案:将系统的核心功能封装为系统调用,供应用程序使用
综上所述,不一定需要系统调用
系统调用与中断的联系
系统调用必须使用中断,系统调用是一种软中断,因此做题的时候直接把系统调用看成中断的一种类型即可
4 操作系统体系结构
考察范围即体系结构
4.1 认识大内核与微内核设计
4.1.1 操作系统内核位置分布
接着我们再对内核进行细分:分成时钟管理、中断处理、原语以及各个功能管理
对于时钟管理、中断处理、原语是与硬件结合最为紧密的,必须要将其放在内核当中
对于有些操作系统并不将这些功能管理放到内核中,称为微内核
4.1.2 介绍微内核和大内核
两种设计结构如下图所示:
描述:应用程序想要请求操作系统的服务,这个服务的处理同时涉及到进程管理、存储管理、设备管理
采用大内核
此时应用程序向操作系统提起服务,CPU会用户态切换为核心态,只需要进行两次变态即可。
采用微内核
向操作系统发起命令,功能管理属于用户态,但在实际使用的时候依旧需要内核的支持,一个功能管理就需要进行两次变态,涉及到三个,因此需要六次变态。
对于功能管理与内核之间是通过消息传递来进行的:
- 向微内核中发送一个消息,在消息里边指明了调用谁以及对应的参数,
- 将消息传递到指定的管理模块(例如存储管理)
- 管理模块接收到进程管理这个消息之后,才会处理这个调用的请求
如果要得到调用结果也是通过消息传递的方式,让微内核协助各个模块之间的调用以及返回。
显然,相对于大内核直接进行函数调用比消息传递快得多。
优缺点总结
因此可以总结出大内核和微内核优缺点:
注意:大内核某个功能模块出错,可能导致整个系统出错,这是因为功能模块联系紧密
4.2 分层结构
点说明
1(重点关注)、便于调试和验证,自底向上逐层调试验证。
- 说明:第一层只会使用到底层的硬件,硬件厂商在出厂各个硬件的时候就已经保证了功能是否正确,只需要去调用第一层的代码进行调试就可以了。第二层的调试是基于正确的第一层来进行的,之后依照一层一层往外调试,只有一层验证ok才会再去验证下一层,此时就能够将软件测试的这个过程变得十分清晰明朗。
2、易于扩充与维护,各层之间接口清晰固定。
- 说明:这类分层结构在操作系统内核设计的时候就确定的,对于层与层之间调用接口、函数名、调用的参数提供哪些参数含义,每个调用返回值,都是在最初设定好的。由于层间调用接口固定不变,因此可以在两层之间添加一层新的,只要保证原来的接口不变就可以,十分方便维护。
缺点说明
1、仅可调用相邻底层,难以合理定义各层的边界。
- 说明:比如第3层与第4层,只能第4层去调用第3层,第3层不能调用第4层,所以对于高层只能调用底层的约定很不灵活。
2(重点关注)、效率低,不可跨层调用,系统调用执行时间长。
- 例如图中,如果只想要使用A中的某个功能,如果没有限制可以直接通过D->A即可得到结果,而按照规定限制,只能够通过D->C->B->A的链路完成功能,导致系统调用的时间,执行时间变长,效率低。
4.3 模块化
操作系统的内核划分为多块,模块之间相互协作工作,如下图将操作系统分为进程管理、存储器管理、文件管理,对于各个管理又再一次进行细分:
内核=主模块+可加载内核模块
- 主模块:指的是进程、内存…这些重要模块。
- 可加载内核模块:可以动态加载到操作系统的内核模块。例如设备驱动程序,对于这个模块可有可无,即使没有也不会影响到操作系统的运行,只是会影响到操作系统的可扩展性。
模块化操作系统的优点
1、模块间逻辑清晰易于维护,确定模块间接口后即可多模块同时开发。
- 说明:易于维护指的是某个模块用来管进程,有的模块用来管内存。确定模块间接口就是明确各个函数功能、参数,返回值,那么就算当前的功能模块没有实现,也可以按照约定在模块之间进行开发
2(重点关注)、支持动态加载新的内核模块(如:安装设备驱动程序、安装新的文件系统模块到内核),增强OS适应性。
- 说明:加载新的模块不需要重新编译某个内核。
3(重点关注)、任何模块都可以直接调用其他模块,无需采用消息传递进行通信,效率高。
- 说明:各个模块之间,如果要使用一个功能管理部分的功能,就直接调用函数即可。这种方式可以使得功能的调用效率非常高。在微内核中就需要使用消息出传递的方式来调用其他模块所提供的功能。
模块化操作系统的缺点
1、模块间的接口定义未必是合理、使用。
- 说明:由于各个模块之间相互调用的比较多,对于模块之间的互相调用功能会出现问题。
2、模块间相互依赖,更难调试和验证。
4.5 外核
应用程序可以通过系统提供的库函数来去调用普通内核中的一些功能,也可以通过库函数直接调用外核所提供个功能。
在这种操作系统中,操作系统=内核+外核:
- 内核:负责进程调度、进程通信等功能和硬件资源无关的工作。
- 外核:负责为用户进程分配未经抽象的硬件资源(例如磁盘的存储空间、内存的存储空间),且由外核负责保护资源使用安全。
对于 未经抽象的硬件资源 的解释:
- 抽象过的硬件资源:在普通的操作系统中,如果用户进程想要使用一片内存空间,给它分配的是经过抽象的虚拟化的空间,对于用户视角是连续的一块空间,而实际物理空间则可能是离散的,对于外存分配空间也是一样的。(用户不能够自己控制这块硬件资源的连续与离散)
- 未经抽象的硬件资源:作为外核是可以直接给用户进程分配的,此时该进程可以去向外核申请一整片连续的磁盘块,作为外核可以直接分配这一块实实在在的物理空间,而不是虚拟的,经过抽象的地址空间。(用户能够去控制硬件资源的连续,可以向外核申请)
针对于上述,对于得到的离散的一块磁盘空间在实际访问的时候磁头会来回横跳,影响效率,所以对于有外核的相对来说能够由更加高的灵活度。
对于 外核负责保护资源使用安全 的解释:进程A向外核分配一块E区间,如果其他进程访问这块E区间,这种行为会被外核发现并制止,同时进程A如果访问的不是它自己申请的一块空间同样也会被发现和制止,所以作为外核它分配了这些硬件资源之后,还需要保证这些硬件资源的使用安全。
优点说明
1(重点关注)、外核可直接给用户进程分配"不许你、不抽象"的硬件资源,使用户进程可以更灵活的使用硬件资源。
2(重点关注)、减少了虚拟硬件资源的"映射层",提升效率。
- 说明:①普通的操作系统为用户分配的都是虚拟的硬件资源,例如虚拟内存,对于一个用户在访问自己的地址空间,给出的是虚拟地址,操作系统需要去查页表,有时需查二级、三级页表,通过多次访存后才能够把虚拟地址转换为实际的物理地址,因此映射的时间则是需要时间开销的。
- ②使用了外核分配的未抽象的硬件资源,无需经过映射转换确定物理地址,直接拿的就是物理地址,此时就能够提升效率。
缺点说明
1、降低了系统的一致性。
- 如果p1申请虚拟空间,p2申请物理空间,p1需要映射,p2不需要映射,分配内存策略和管理需要考虑很多情况,导致一致性降低
2、使系统变得更复杂。
4.6 总结
红色为大纲新增加的,黄色则是之前大纲的。
5 操作系统引导
5.1 安装操作系统后磁盘的数据类型
安装完操作系统后,我们磁盘分布如下:
- 主引导记录MBR(Master Boot Record):包含了磁盘引导程序和分区表。
- 分区表:实际就是一个数据结构,说明了在磁盘中每一个盘每一个分区分别占多大的空间以及每个分区的地址范围。
由于C盘中安装了操作系统,此时C盘可以称为磁盘的活动分区。
C盘进行细分:包含引导记录PBR、根目录、其他
- 引导记录PBR(Partition Boot Record):主要目的是用来找到启动管理器。
- 根目录:就是双击C盘打开看到的内容
5.2 操作系统引导(开机过程)
操作系统引导一定是从CPU开始的,下面是对应的CPU与主存:
主存由ROM和RAM组成。
- RAM:断电数据就丢失了。
- ROM(BIOS,Basic Input/Output System):基本输入输出系统,其中包含了ROM引导程序(自举程序),断电数据不会丢失。
其开机过程如下:
- CPU通电,去主存当中固定的位置开始读指令,执行ROM引导程序(先进行硬件自检,再开机)
- 在ROM引导程序中,指示CPU把磁盘的主引导记录及分区表给读入到内存。
- 执行磁盘引导程序,扫描分区表。磁盘引导程序根据分区表从活动分区读取分区引导记录PBR(该引导程序本质依旧是一个程序)。
- 执行引导记录程序PBR,PBR从根目录里找到启动管理程序。CPU再执行启动管理程序完成操作系统初始化开机的一系列工作。
- 启动管理器:通常存放在C盘中的对应的根目录里某个位置。
6 虚拟机
6.1 传统计算机
传统的计算机在一个物理机器上只能够运行一个操作系统。对于一个操作系统商运行两个进程,它们之间可能会相互影响,也会相互争夺操作系统管理的资源。实际在商业环境中,两个应用让他们同时在一个操作系统商运行就会造成一些隐患。
一种解决方案:将启动的一个应用服务迁移到另一台物理机上。
缺点:这种方案对于真正的商业级物理机比较浪费。本身商业级的硬件性能十分强大,本身硬件性能是可以支持两个进程的,但是又为了安全起见不得将另一个应用迁移到另一台机器上运行。
6.2 虚拟机
6.2.1 基本概念
虚拟机:使用虚拟化技术,将一台物理机器虚拟化为多台虚拟机器(Virtual Machine,VM),每个虚拟机器都可以独立运行一个操作系统。
- 同义术语:虚拟机管理程序、虚拟机监控程序(Virtual Machine Monitor/Hypervisor)。统一先试用虚拟机管理程序来表示虚拟机。
虚拟机管理程序分为两类:第一类VMM(运行在硬件之上);第二类VMM(运行在宿主机之上)。
6.2.2 第一类VMM(运行在硬件之上)
由虚拟机管理程序将一台物理机虚拟化为多个部分,在每一台虚拟机上安装各自的操作系统,例如第1台Windows、第2台Linux、第3台Windows,在每一个操作系统商都可以运行各自的用户程序。
将一个机器上的硬件资源分配给各个虚拟机器?
例如:多台虚拟机中使用的CPU实际是同一个,分配若干个时间片平均分配给每个虚拟机器。内存,磁盘根据虚拟机数量进行空间的划分分配给多个虚拟机
对于上层的操作系统运行在用户态,它们可以使用特权指令吗?
当上层的操作系统想要使用特权指令的时候,它的行为会被虚拟机管理程序截获,虚拟机管理程序会把上层操作系统的特权指令做一些等价转换,模拟出指令成功的感觉。
注意:只有虚拟机管理程序是运行在内核态的,只有它才可以运行特权指令。
6.2.3 第二类VMM(运行在宿主机之上)
这一类虚拟机管理程序是运行在一个宿主机OS上,我们在宿主机OS上可以下载这个虚拟机管理程序软件:
注意:第二类中如果想要给虚拟机器分配硬件资源,那么只能够请求操作系统给它分配(管理者),第二类虚拟机管理程序则是在用户态运行(部分是在内核态)。
6.2.4 两类虚拟机管理程序对比
补充说明
资源分配方式:
对于外存的分配:
- 第一类:以管理者角色可以直接对资源进行划分(与之前外核分配资源方式类似);
- 第二类:虚拟机管理程序想要分配的资源是抽象的,它会向操作系统申请创建10GB的大文件(对于具体存放位置由宿主机决定,分配的虚拟磁盘未必是连续的),分配得到过后它再分配给指定的虚拟机。
对于内存的分配也类似:虚拟机管理程序向操作系统申请获得的是4G虚拟内存,获取到虚拟内存之后,再将虚拟内存进行拆分分给两个虚拟机器,各自2GB。
性能
第一类虚拟机管理程序性能更好,第二类虚拟机管理程序性能更差。
- 假设Host OS分配虚拟内存4GB给VMM,VMM又将这4GB虚拟内存合理分配给VM1,VM2操作系统。这就导致了,VM1,VM2使用这些硬件资源时,地址需要先映射为VMM获得的虚拟内存的地址空间,而宿主操作系统则需要把虚拟地址空间映射到实际的物理地址空间,导致了需要多层映射,因此性能差
可支持的虚拟机数量
第一类更多
原因:第一类的虚拟机管理程序拥有所有的硬件资源,第二类的虚拟机管理程序对于所需资源需要向操作系统申请,并且其本身需要一些硬件资源,同时宿主操作系统上进程依旧需要一些硬件资源。
所以在硬件资源相同的情况下,第一类能够支持更多的虚拟机。
虚拟机迁移程序
第一类更差,第二类更好。
- 第一类迁移十分的麻烦。
- 第二类使用的是虚拟机管理程序软件,例如使用virtualbox,只需要将对应的操作系统导出为iso文件,其他人如果使用同一个操作系统(包含上面软件)只需要创建虚拟机导入即可,使用十分灵活。
运行模式
- 第一类VMM运行在Ring 0(0环,最高级别),上层系统运行在次高优先级;
- 第二类VMM部分运行在用户态,部分运行在内核态,对于虚拟机中发出的系统调用会被VMM截获再转化为VMM对Host OS(宿主机)的系统调用。
Ring 0的含义:最近几年的CPU特权级别会被更多层次的划分,最高级则是零级,之后越往上权限越低。
为什么采用这种划分更多的特权级别有好处?
- 假设划分不详细,只有非特权指令和特权指令。拿第二类虚拟机管理程序举例,对于虚拟机中的操作系统如果发起系统调用,虚拟机管理程序则需要将其截获并且去判断该特权指令是否合法,如果合法还需要由其来进行模拟,再发给宿主机最终模拟出特权指令执行的效果。
- 如果划分详细。拿第一类举例,虚拟机管理程序运行在最高权限0,客户操作系统内核运行在一环,此时上层客户操作系统使用一环二环指令,作为虚拟机管理程序就无需进行管理,直接执行即可,只对零环的调用系统指令才会检查。
- 好处:虚拟机不用检查每一条特权指令的执行,只需要检查某一些敏感指令的执行即可