操作系统学习
一.操作系统概述
1.概念、功能
操作系统是指控制和管理整个计算机系统的硬件和软件资源,并合理地组织调度计算机的工作和资源的分配,以提供给用户和其他软件方便的接口和环境
命令接口和程序接口统称为用户接口
没有任何软件支持的计算机称为裸机,通常把覆盖了软件的机器称为扩充机器,又称之为主机
2.特征
①并发性:宏观上同时发生,微观上交替发生(并行:同时发生)
注意:
- 单核CPU同一时刻只能执行一个程序,各个程序只能并发地执行
- 多核CPU同一时刻可以同时执行多个程序,多个程序可以并行地执行
②共享性:系统中的资源可供内存中多个并发执行的进程共同使用
两种资源共享方式:
- 互斥共享方式:一段时间内只允许一个进程访问该资源
- 同时共享方式:允许多个进程“同时”对它们进行访问
③虚拟性:将一个物理上的实体变为若干个逻辑上的对应物
虚拟技术:
- 空分复用技术(如虚拟存储器技术)
- 时分复用技术(如虚拟处理器)
④异步性:进程的执行的执行不是一贯到底的,而是断断续续,以不可预知的速度向前推进
总结:并发和共享互为存在条件,没有并发和共享,就谈不上虚拟和异步
3.发展历史和分类
4.运行机制
graph LR
A(操作系统的运行机制)-->B1(简单了解程序的运行原理)
B1-->C1(高级语言编写代码->机器指令)
B1-->C2(程序运行的过程就是CPU执行指令的过程)
A-->B2(两类程序)
B2-->D1(内核程序)
B2-->D2(应用程序)
A-->B3(两类指令)
B3-->E1(特权指令)
B3-->E2(非特权指令)
A-->B4(两种处理器状态)
B4-->F1(内核态/核心态/管态)
B4-->F2(用户态/目态)
D1-.only.->E1
E1-.only.->F1
D1-.only.->F1
A-->B5(内核)
B5-->G1("内核(Kernel)是操作系统最核心的部分")
B5-->G2(由很多内核程序组成操作系统内核)
A-->B6(如何变态?)
B6-->H1(内核态->用户态)
H1-->I1(一条修改PSW的特权指令)
B6-->H2(用户态->内核态)
H2-->I2(由中断引起,硬件自动完成)
5.中断和异常
CPU上会运行两种程序,一种是操作系统内核程序,一种是应用程序
中断的作用:让操作系统内核夺回CPU使用权的唯一途径
中断(广义的中断)分为内中断和外中断
内中断与当前执行的指令有关,中断信号来自于CPU内部
外中断反之
内中断(也称为异常)的例子:试图在用户态下执行特权指令,执行除法指令时除数为0,执行陷入指令(非特权指令)
外中断(狭义的中断)的例子:时钟中断(由时钟部件发送的中断信号),I/O中断请求
每个指令周期末尾,CPU都会检查是否有外中断信号需要处理
基本原理:不同的中断信号,需要不同的中断处理程序来处理。当CPU检测到中断信号后,会根据中断信号的类型去查询"中断向量表",以此找到相应的中断处理程序在内存中的存放位置
6.系统调用
系统调用是操作系统提供给应用程序使用的接口,可以理解为一种可供应用程序调用的特殊函数,应用程序可以通过系统调用来请求获得操作系统内核的服务
有的库函数是对系统调用的进一步封装,有的库函数没有使用系统调用
系统调用的过程:
- 前期处理相关指令
- 传参指令(将系统调用需要的参数放到某些通用寄存器中)
- 陷入指令(引发内中断)
- 后续处理相关指令
陷入指令=trap指令=访管指令
7.操作系统体系结构
层次结构:
上述图片是大内核结构
将进程管理、存储器管理、设备管理排除内核之外的是微内核结构
微内核需要频繁地在核心态和用户态切换,性能低,但是方便维护
操作系统结构总结:
8.操作系统的引导
图解:
步骤:
- CPU从一个特定的主存地址开始,取指令,执行ROM中的引导程序(先进行硬件自检,再开机)
- 将磁盘的第一块–主引导记录读入内存,执行磁盘引导程序,扫描分区表
- 从活动分区(主分区,即安装了操作系统的分区)读入分区引导记录,执行其中的程序
- 从根目录下找到完整的操作系统初始化程序(即启动管理器)并执行,完成"开机"的一系列动作
9.虚拟机
虚拟机:使用虚拟化技术,将一台物理机器虚拟化为多台虚拟机器,每个机器都可以独立运行一个操作系统
作用:充分利用硬件资源
同义术语:虚拟机管理程序=虚拟机监控程序=Virtual Machine Monitor(VMM)=Hypervisor
两类虚拟机管理程序:
两类VMM对比:
二.处理机管理
1.进程的概念、组成、特征
程序:是静态的,是存放在磁盘内的可执行文件
进程:是动态的,是一次程序的执行
当进程被创建时,进程会被分配一个PID
数据结构PCB(Process Control BLock),即进程控制块,进程管理所需要的所有信息,都会放在PCB中
PCB是进程存在的唯一标志,PCB在进程结束时会被回收
一个进程实体由PCB、程序段、数据段组成
程序段包含程序指令,数据段包含产生的各种数据
进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位
进程的特征:
- 动态性
- 并发性
- 独立性
- 异步性
- 结构性
2.进程的状态与转换、组织的方式
进程的状态:创建态(新建态)、就绪态、运行态、阻塞态(等待态)、终止态(结束态)
进程的转换图:
在PCB中,会有一个变量state来表示进程的当前状态
进程的组织方式:
- 链接方式(多)
- 按照进程状态将PCB分为多个队列
- 操作系统持有指向各个队列的指针
- 索引方式
- 根据进程状态的不同,建立几张索引表
- 操作系统持有指向各个索引表的指针
3.进程控制
进程控制:实现进程的状态转换
进程控制由原语实现,原语有原子性,必须一气呵成
可以用"关中断指令"和"开中断指令"这两个特权指令实现原子性
进程控制相关的原语:
- 创建原语
- 申请空白PCB
- 为进程分配所需资源
- 初始化PCB
- 将PCB插入就绪队列
- 撤销原语
- 从PCB集合中找到终止进程的PCB
- 若进程正在运行,立即剥夺CPU,将CPU分配给其它进程
- 终止其所有子进程
- 将该进程拥有的所有资源归还给父进程或操作系统
- 删除PCB
- 撤销原语
- 从PCB中找到终止进程的PCB
- 若进程正在进行,立即剥夺CPU,将CPU分配给其他进程
- 终止其子进程
- 将该进程的所有资源归还给父进程或操作系统
- 删除PCB
- 阻塞原语
- 找到要阻塞的进程对应的PCB
- 保护进程运行现场,将PCB状态信息设置为"阻塞态",暂时停止进程运行
- 将PCB插入相应事件的等待队列
- 唤醒原语
- 在事件等待队列中找到PCB
- 将PCB从等待队列移除,设置进程为就绪态
- 将PCB插入就绪队列,等待被调度
4.进程通信
进程通信(IPC)指的是两个进程之间产生数据交互
进程是分配系统资源的单位(包括内存地址空间),因此各进程拥有的内存地址空间相互独立
共享存储区实现进程通信:
基于存储区的共享:这种共享方式速度快,是一种高级通信的方式
基于数据结构的共享:比如在共享空间里只能放一个长度为10的数组。这种方式速度慢,是低级通信方式
另一种通信方式,消息传递:进程间的数据交换以格式化的消息为单位。进程通过操作系统提供的“发送消息/接收消息”两个原语进行数据交换
graph LR
A(进程通信)-->B1(直接通信)
A-->B2(间接通信)
A-->B3(管道通信)
B1-->C1(消息直接挂到接收进程的消息队列里)
B2-->C2("消息先发到中间体(信箱)")
B3---C3(管道是一个特殊的共享文件<br>其实就是在内存中开辟一个大小固定的内存缓冲区<br>数据结构可以看为一个循环队列<br>一段时间只能实现单向的传输<br>管道的数据一旦被读出,则彻底消失)
5.线程
线程可以理解为轻量级进程,是一个基本的CPU执行单元,也是程序执行流的最小单位
作用:提升系统的并发度,各线程的代码可以同时进行
引入线程后,进程只作为除CPU之外的系统资源的分配单元
多CPU计算机中,各个线程可以占用不同的CPU
线程的控制块叫TCB
线程也有就绪、阻塞、运行三种基本状态
切换进程,系统开销大。切换同进程内的线程,系统开销很小
6.线程的实现方式和多线程模型
①用户级线程:
早期的操作系统只支持进程,线程是由程序员写的线程库完成的
从用户视角能看到的线程
缺点:一个线程被阻塞,整个进程都会被阻塞,多个线程不能再多核处理机上同时运行
②内核级线程(一对一模型):
从操作系统视角看到的线程
缺点:线程切换需要CPU从用户态转换为内核态,开销大
③多对一模型:
缺点:一个线程被阻塞,整个进程都会被阻塞,多个线程不能再多核处理机上同时运行
④多对多模型:
用户级线程是"代码逻辑"的载体
内核级线程是"运行机会"的载体
7.线程的状态和转换
graph LR
A(就绪)-.③被调度程序选中.->B(运行)
B-.①等待某事件.->C(阻塞)
C-.④等待的事件发生.->A
B-.②时间用完.->A
TCB也有TID,与PID类似
多个线程组织起来就是线程表
8.调度的概念和层次
确定某种规则来决定处理任务的顺序,这就是调度研究的问题
作业:一个具体的任务
高级调度(作业调度):每个作业只调入一次,调出一次。作业调入时会建立PCB,调出才撤销PCB
低级调度(进程调度/处理机调度):按照某种策略从就绪队列中选取一个进程,将处理机分配给它
内存不够时,可将某些进程的数据调出外存。暂时调到外存等待的进程状态为挂起状态。被挂起的进程PCB会被组织成挂起队列
中级调度:按照某种策略决定将哪个处于挂起状态的进程重新调入内存
挂起态与七状态模型
挂起态分为就绪挂起、阻塞挂起两种状态
调度 | 发生在… | 发生频率 | 对进程状态的影响 |
---|---|---|---|
高级调度 (作业调度) | 外存->内存 | 最低 | 无->创建态->就绪态 |
中级调度 (内存调度) | 外存->内存 | 中等 | 挂起态->就绪态 |
低级调度 (进程调度) | 内存->CPU | 最高 | 就绪态->运行态 |
9.调度的时机、切换与过程、方式
进程调度的时机:
- 进程主动放弃处理机
- 进程正常终止
- 运行过程中发生异常而终止
- 进程主动请求阻塞
- 被动放弃处理机
- 分给进程的时间片用完
- 有更紧急的是需要处理
- 有更高优先级的进程进入就绪队列
- 不能调度的情况
- 在处理中断的过程中
- 在操作系统内核程序临界区中
- 在原子操作过程中(原语)
进程调度的方式:
- 非剥夺方式(非抢占式):只能由当前运行的进程主动放弃CPU
- 剥夺调度方式(抢占式):可由操作系统剥夺当前进程的CPU使用权
狭义的进程调度指的是从就绪队列中选一个要运行的进程
广义的进程调度包含了选中一个进程和进程切换两个步骤
进程调度、切换是由代价的,不是调度越频繁,并发度越高
10.调度器和闲逛进程
就绪和运行之间的②和③由调度程序引起
调度程序决定:调度算法、时间片大小
调度时机(会引发调度程序的事件):
- 创建新进程
- 进程退出
- 运行进程阻塞
- I/O中断发生
当CPU没有其他就绪进程时,会运行闲逛进程
闲逛进程的特性:
- 优先级最低
- 可以是0地址指令,占一个完整的指令周期
- 能耗低
11.调度算法的评价指标
①CPU利用率: 利用率 = 忙碌的时间 总时间 利用率=\frac{忙碌的时间}{总时间} 利用率=总时间忙碌的时间
②系统吞吐量: 系统吞吐量 = 总共完成了多少道作业 总共花了多少时间 系统吞吐量=\frac{总共完成了多少道作业}{总共花了多少时间} 系统吞吐量=总共花了多少时间总共完成了多少道作业
③周转时间:
周转时间
=
作业完成时间
−
作业提交时间
周转时间=作业完成时间-作业提交时间
周转时间=作业完成时间−作业提交时间
平均周转时间
=
各作业周转时间之和
作业数
平均周转时间=\frac{各作业周转时间之和}{作业数}
平均周转时间=作业数各作业周转时间之和
带权周转时间
=
作业周转时间
作业实际运行的时间
=
作业完成时间
−
作业提交时间
作业实际运行的时间
带权周转时间=\frac{作业周转时间}{作业实际运行的时间}=\frac{作业完成时间-作业提交时间}{作业实际运行的时间}
带权周转时间=作业实际运行的时间作业周转时间=作业实际运行的时间作业完成时间−作业提交时间
平均带权周转时间
=
各作业带权周转时间之和
作业数
平均带权周转时间=\frac{各作业带权周转时间之和}{作业数}
平均带权周转时间=作业数各作业带权周转时间之和
④等待时间:
对于进程来说,进程建立后等待被服务的时间之和
对于作业来说,建立进程后的等待时间+作业在外存后备队列中等待的时间
⑤响应时间:从用户提交请求到首次产生响应所用的时间
12.调度算法
饥饿:某进程/作业长期得不到服务
①先来先服务的算法(FCFS):
非抢占式的算法,缺点:带权周转时间很大,对长作业有利,对短作业不利,不会导致饥饿
②短作业优先(SJF):
用于进程调度时称为短进程优先算法(SPF)
SJF和SPF是非抢占式的算法,但是也有抢占式的版本–最短剩余时间优先算法(SRTN)
提到短作业优先算法默认是非抢占式的
优点:"最短"的平均等待时间、平均周转时间
缺点:对短作业有利,对长作业不利,若短作业源源不断,则长作业可能饥饿
③高响应比优先算法(HRRN):
响应比
=
等待时间
+
要求服务时间
要求服务时间
响应比=\frac{等待时间+要求服务时间}{要求服务时间}
响应比=要求服务时间等待时间+要求服务时间
非抢占式的算法
不会导致饥饿
④时间片轮转算法(RR):
按照各进程到达就绪队列的顺序,轮流让各个进程执行一个时间片。若时间片结束,则重新排队
抢占式的算法
缺点:进程切换导致一定的开销,不区分任务的紧急性
不会导致饥饿
⑤优先级调度算法:
有抢占式和非抢占式的版本
就绪队列未必只有一个,可以按照不同优先级来组织,另外,也可以把优先级高的进程排在更靠近队头的位置
通常:
- 系统进程优先级高于用户进程
- 前台进程优先级高于后台进程
- 操作系统更偏好I/O型进程
缺点:可能导致饥饿
⑥多级反馈队列调度算法:
设置多级就绪队列,各级队列优先级从高到低,时间片从小到大。新进程到达时先进入第一级队列,按FCFS原则排队等待被分配时间片。若时间片用完还未结束,则进程进入下一队列队尾
若已在最下级的队列,则重新放回最下级队列队尾
只有第k级队列为空时,才会为k+1级队头的进程分配时间片
是抢占式的算法
被抢占处理机的进程重新放回原队列队尾
可能会导致饥饿
⑦多级队列调度算法:
13.进程同步、进程互斥
进程具有异步性
同步亦称直接制约关系,它是指为完成某种任务而建立的两个或多个进程,这些进程需要再某些位置上协调它们的工作次序而产生的制约关系
我们把一个时间段内只允许一个进程使用的资源称为临界资源,如内存、打印机和摄像头
互斥亦称间接制约关系,进程互斥是指当一个进程访问某临界资源时,另一个想要访问该临界资源的进程必须等待
进程互斥需要遵循的原则:
- 空闲让进:临界区空闲时,应允许一个进程访问
- 忙则等待:临界区正在被访问时,其它试图访问的进程需要等待
- 有线等待:要在优先时间内进入临界区,保证不会饥饿
- 让权等待:进不了临界区的进程,要释放处理机,防止忙等待
14.进程互斥的软件实现方法
①单标志法:两个进程在访问完临界区后会把使用临界区的权限转交给另一个进程。也就是说每个进程进入临界区的权限只能被另一个进程赋予
缺点:不遵循空闲让进的原则
②双标志先检查法:设置一个布尔型数组flag[],数组中各个元素用来标记各进程想进入临界区的意愿。flag[0]=true意味着0号进程P0现在想要进入临界区。每个进程在进入临界区之前先检查当前有没有别的进程想进入临界区,如果没有,则把自身对应的标志flag[i]设为true,之后开始访问临界区
缺点:违反忙则等待的原则
③双标志后检查法:先上锁再检查
缺点:违背空闲让进和有限等待的原则,可能会导致饥饿
④Peterson算法:结合双标志法、单标志法的思想。如果双方都想进入临界区,那可以让进程尝试谦让
缺点:没有遵循让权等待的原则
15.进程互斥的硬件实现方法
①中断屏蔽方法:利用"开/关中断指令"实现
缺点:开中断和关中断只能作用于当前处理机,所以该方法不适用于多处理机。开中断和关中断只能在内核态执行,不适用于用户进程
②TestAndSet(TS、TSL)指令:TSL指令是用硬件实现的,执行的过程不允许被中断,只能一气呵成
缺点:不遵循让权等待的原则
③Swap指令:有的地方叫Exchange指令,或简称XCHG指令
Swap指令是用硬件实现的,执行的过程不允许被中断,只能一气呵成
缺点:不遵循让权等待的原则
16.互斥锁
解决临界区最简单的工具就是互斥锁。一个进程在进入临界区时应获得锁,在退出临界区时释放锁
互斥锁的缺点是忙等待。需要连续循环忙等待的互斥锁,都可称为自旋锁,如TSL指令、Swap指令、单标志法
不适用于单处理机系统
17.信号量机制
用户进程可以通过使用操作系统提供的一对原语(原语的执行一气呵成,不可中断)来对信号量进行操作,从而方便的实现了进程互斥、进程同步
信号量其实就是一个变量,可以用一个信号量来表示系统中某种资源的数量
一对原语:wait(S)原语和signal(S)原语,分别可以简写为P、V操作,括号里的信号量S其实就是函数调用时传入的一个参数
用一个整型信号量可以表示系统中某种资源的数量,对信号量的操作只有三种:初始化、P操作、V操作
缺点:不遵循让权等待的原则
记录型信号量:用来记录型数据结构表示的信号量
18.用信号量机制实现进程同步、互斥、前驱关系
信号量机制实现进程互斥
- 分析并发进程的关键活动,划定临界区
- 设置互斥信号量mutex,初值为1(mutex表示进入临界区的"名额")
- 在进入区P(mutex)–申请资源
- 在退出区V(mutex)–释放资源
注意:对不同的临界资源需要设置不同的互斥信号量
信号量机制实现进程同步
进程同步:要让各并发进程按要求有序地推进
实现:
- 分析什么地方需要实现"同步关系",即必须保证"一前一后"执行的两个操作(或两句代码)
- 设置同步信号量S,初始值为0
- 在"前操作"之后执行V(S)
- 在"后操作"之前执行P(S)
信号量机制实现前驱关系
- 分析问题,画出前驱图,把每一对前驱关系都看成一个同步问题
- 要为每一对前驱关系各设置一个同步信号量,初值为0
- 在"前操作"之后对相应的同步信号量执行V操作
- 在"后操作"之前对相应的同步信号量执行P操作