1. 第一章
1.1 指令执行的基本指令周期
基本指令周期:取指令、执行
基本流程:开始->将PC所指地址中的指令读入IR,PC++(取指令阶段
)->执行IR中的指令(执行阶段
)->结束
IR:instruction register,指令寄存器
PC:program counter,程序计数器
四类指令:
- 处理器-存储器:在
寄存器
和内存单元间
传送数据
- 处理器-I/O:
处理器
和I/O设备
间传送数据
- 数据处理:算术/逻辑运算
- 控制转移:设置PC值,改变执行顺序
1.2 中断的定义与分类
- 中断的定义:由于发生某些事件,暂停当前程序在CPU上的运行,转而去执行相应事件的
中断处理程序
。待处理完成后,再返回断点继续执行
或者调度其他程序执行
- 中断分类
- 程序中断:由程序指令的执行结果产生,如算术溢出、除数为0、非法指令、地址越界、缺页、断点调试等
- 时钟中断:CPU内部的计时器产生
- I/O中断:I/O控制器正常或者异常结束时,由I/O控制器产生
- 硬件失效中断:掉电、内存奇偶校验错等硬件故障
1.3 中断的处理
1.3.1 对程序控制流的影响
- 无中断时的处理流程:首先程序在CPU上运行,正在执行非I/O指令,此时程序提出I/O请求,程序流被打乱,开始执行I/O程序,先执行
I/O参数设置
,然后执行I/O操作,完成I/O后设置完成状态。此时回到原程序流,继续执行剩余的程序指令流。
- 有中断时的处理流程:首先程序在CPU上运行,正在执行非I/O指令,此时程序提出I/O请求,程序流被打乱,开始执行I/O程序,先执行
I/O参数设置
,然后在I/O操作开始执行的同时,CPU回到原程序流,继续执行剩余的非I/O指令,当I/O完毕时,发出中断信号,中断处理程序启动,完成剩余的I/O程序操作(设置完成状态等),完成后回到原程序流继续执行。
- 在
有中断的处理流程中
,I/O操作分为短I/O和长I/O:
- 短I/O:下段非I/O指令尚未执行完,本次I/O已经结束,并发出中断
- 长I/O:本次I/O请求时间长,尚未结束时已经发生了下次的I/O请求,则将该I/O请求排入请求队列,顺序处理各个请求
1.3.2 对CPU的影响
- 无中断时:CPU和I/O设备是
串行
工作,也就是一个设备必须等待另外一个设备操作结束
- 有中断时:CPU和I/O设备是
并行
工作,CPU完成更多任务,I/O操作期间,CPU继续执行其他任务,提高CPU利用率
1.3.3 中断处理机制
- CPU在执行完一条指令之后、执行下一条指令之前,检测并处理中断
- 有中断时的指令周期
- 此时指令周期可以分为三个阶段,也就是取指阶段、执行阶段、中断阶段
- 大致流程:①开始->②进入取指阶段(取下一条指令)->③进入执行阶段(执行指令)->如果允许中断,进入④,如果不允许中断,返回②,④检查中断信号,初始化中断处理程序,当程序流中的所有指令都执行完毕后,停止。
1.3.4 中断处理-硬件连接
- CPU和
中断控制器
之间用总线上的中断请求线连接
连接。设备发出中断后,CPU响应中断
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3ssiWYGx-1655605190868)(.\image\硬件响应.png)]
- 看图说话:首先disk作为I/O设备,进行I/O,当I/O操作结束之后,DISK向中断控制器发出中断信号,中断控制器(中断请求线)转发中断信号给CPU,CPU在执行完一条指令后,执行下一条指令前,接收该中断信号,CPU处理该中断。
1.3.4 中断处理的软件实现
- 每个中断都有一个中断向量号,是该中断在中断向量表中的编号
- 中断向量:中断处理程序的(内存)入口地址。4B/向量
- 中断向量表:所有中断向量的集合,一般位于内存的0地址起始处(长1KB),在开机启动时从磁盘装入内存
- 以上的数据结构规定了一种中断处理模式,每一种处理有自己的编号,根据此编号可以在中断向量表中找到对应的中断类型,在对应的中断类型中对应一个中断处理程序(地址),当发生某种中断时,依照这个链条去寻找中断处理程序
1.3.5 中断处理的过程
- 由硬件执行的部分:设备发出中断信号->CPU执行完当前指令->CPU向设备发中断应答信号->CPU将PSW和PC压栈(保存现场)->根据(中断向量表),CPU设置新PC值
- 由中断处理程序执行的部分:将其它寄存器的值压栈->执行中断处理程序->恢复被中断程序的现场(包括原PSW和原PC)->返回原程序断点,继续执行
1.3.6 多个中断-两种处理方法
- 顺序处理:当处理一个中断时,禁止中断。多个中断被顺序处理。
- 禁止中断(关中断):CPU的PSW的中断禁止位=0,则不响应新的中断
- 开中断:中断禁止位,CPU可以接收中断
- 中断嵌套:允许高优先级的中断请求打断低级中断的处理。通常,中断源速度越快,其优先级越高
- 中断屏蔽:设置PSW的中断屏蔽码(当前程序的中断优先级),选择性地封锁部分中断,当发生更高优先级的中断时才响应
- 有些中断(如掉电)是不能屏蔽甚至不能禁止的
1.4 存储器层次
- 内存:CPU能直接访问的唯一大型存储介质
- 为
扩充内存容量
,用磁盘和内存
实现虚拟内存
- 为
加快内存访问速度
,CPU首先访问Cache,不命中时再访问内存且复制进Cache。
- Cache-内存两级存储器:当Cache命中率很高时,平均存取时间接近于Cache访问速度
- 设忽略用于确定Cache是否命中的时间。
Cache不命中时,数据先由内存送到Cache,CPU再访问Cache
- 二级存储器(Cache-内存)下内存的平均存取时间:若T1为
Cache存取时间
,T2为内存存取时间
,H为Cache命中率
,则访问数据的平均存取时间为 H ∗ T 1 + ( 1 − H ) ∗ ( T 2 + T 1 ) H*T1+(1-H)*(T2+T1) H∗T1+(1−H)∗(T2+T1)
- 不同CPU访问Cache-内存时的方式不同(了解)
- 第一种在Cache不命中时,数据从内存->Cache->寄存器
- 第二种则从内存直接送到寄存器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rxWIumcN-1655605190869)(.\image\CPU-Cache.png)]
1.5 程序局部性原理
- 两级存储器有效的原因:
程序的局部性原理
- 时间局部性:在一段小的
时间间隔
内,被访问过的某指令或者数据,可能很快就会被再次访问
- 空间局部性:在一段小的时间间隔内,程序访问的地址空间往往
集中在某个区域(簇)
- 大多顺序执行;经常有循环;过程调用深度有限;数据常为数组、记录;不是所有的代码都需要执行
- 让内存包含所有的(或大部分)指令和数据,而当前访问的”簇“包含在Cache中,可达到高命中率
- 类似地,在虚拟内存中,由"Cache-内存-硬盘"构成三级存储器
怎样改变空间局部性和时间局部性?
空间局部性:更大的Cache块,将数据预取到块中
时间局部性:Cache中保留最近访问的代码和数据
for(int i = 0;i<10;i++){
for(int j = 0;j<10;j++){
a[i] = a[i]*j;
}
}
- 空间局部性
- 执行完第一条指令,执行第二条指令
- 不断访问数组a[]
- 时间局部性
- 循环体被频繁执行
- a[i]在循环内部被访问了10次
2. 第二章
2.1 操作系统的发展过程及其衍生出来的操作系统类型
术语简介:
RAM:主存,与CPU进行直接数据交换的内部存储器
ROM:ROM所存数据,一般是装入整机前事先写好的,整机工作过程中只能读出,而不像随机存储器那样能快速地、方便地加以改写。
BIOS(Basic Input Output System):保存着计算机最重要的基本输入输出的程序、系统设置信息、开机上电自检程序和系统启动自检程序。
- 发展过程
- 人工操作阶段-无OS
- 简单批处理系统-监控程序(
Monitor
):监控程序
使磁带上的一批作业自动、顺序地逐个运行,内存中只有一个作业,故称为单道批处理,监控程序所在的系统内存区含有:中断处理程序
、设备驱动程序
、作业序列
、控制语言解释器
- 作业的组成:用户的程序、数据、作业说明书
- 脱机I/O:程序员把程序卡片拿到卫星机上,读入到"输入磁带"上,操作员把”输入磁带“放进主机,作业在Monitor控制下自动逐个(单道运行),运行结果写到输出磁带上,输出磁带送到卫星机上去打印
- 多道程序设计:由于中断、磁盘、DMA等的引入,使得内存中可以同时存在多个作业,并发执行
- 并发:多个事件在同一时间间隔内发生
- 并行:多个事件在同一时刻发生
- 当正执行的作业需要进行I/O时,可以让出CPU给内存中的其它作业去运行,以提高资源利用率
- 多道批处理OS
- 减少了因CPU与I/O设备串行工作导致的CPU空闲。CPU与I/O设备并行工作,资源利用率高,吞吐率高
- 周转时间长,用户交互性差,整个作业完成后或者中间出错时,才与用户交互,不利于调试和修改
- 分时系统
- 把CPU分割成时间片,每个用户依次轮流使用时间片
- 多个用户通过终端与主机交互。他们的作业按照时间片轮转运行。作业的响应时间短
- 为了满足用户交互和及时响应的要求
- 批处理OS和分时OS的比较
|
批处理OS |
分时OS |
主要目标 |
提高资源利用率 |
减小响应时间 |
OS指令源 |
作业控制语言,作业中的指令 |
终端输入的命令 |
- 实时操作系统:用于实时控制系统和实时信息处理系统
- 严格的时间限制和及时响应
- 高可靠性;如采用冗余的软件或者硬件
- 兼有几种OS特征的通用OS中的前台和后台处理
2.2 多道程序设计如何提高CPU资源利用率
- 当正执行的作业需要进行I/O时,可以让出CPU给内存中的其它作业去运行,以提高资源利用率
3. 第三章
3.1 进程映像
- 进程:程序在一个数据集上的一次执行过程
- 进程与程序的联系与区别
- 程序是静态的;进程是动态的(动态产生并且消亡),且一个进程运行时可以创建其他进程
- 一个进程可对应一个进程,也可以对应多个进程(只要进程所对应的数据集不同)
- 进程的组成(进程映像):
- 程序代码
- 数据集、栈
- 进程控制块(PCB):PCB是进程存在的唯一标识,OS根据PCB中的属性控制进程
- 上下文:进程运行时CPU的寄存器数据集合(现场),包括用户可见寄存器和控制/状态寄存器等
- 分派器(进程调度程序)调度时发生
上下文切换
:保存旧进程的上下文到它的PCB,从新进程的PCB恢复它的上下文到寄存器
- 引入进程,由于实现了并发执行和资源共享,可带来提高
资源利用率
和吞吐率
的好处,但却增加了系统的时间
和空间开销
3.2 进程的创建和终止
进程创建
:OS为该进程建立PCB,分配内存空间
- 导致进程创建的原因
- 新的批处理作业:作业提交后,开始运行时创建进程
- 交互登录:新用户登录和接收用户命令时创建进程
- OS提供服务:如控制打印、网络通信等的服务进程
- 父进程派生子进程:父进程请求创建子进程
进程终止
:回收内存,释放资源,销毁PCB
- 导致进程终止的原因
- 进程正常运行完毕;用户或OS干预;父进程请求或父进程已终止;运行时发生的各种故障和错误
3.3 五状态模型-五状态进程模型
新建
(new):进程正被创建。分配内存后将被设置为就绪态
就绪
(ready):进程已得到除CPU以外的其他所需资源
运行
(running):进程的指令正被执行
阻塞(等待)
(blocked):进程正等待资源或某事件发生
退出
(exit):进程已正常或异常结束。回收资源,善后
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bF1rz6MN-1655605190869)(./image/五状态模型.png)]
假设有些进程处于就绪态,有些处于就绪挂起态,且至少有一个就绪挂起态进程的优先级高于所有就绪态进程。有两种极端策略:
1、总是调度处于就绪态的进程,以减少交换;
2、总是调度优先级最高的进程,会导致不必要的交换。
把就绪挂起进程降低 (1或2个)优先级,如果它仍然高于所有就绪进程的最高优先级,那么就将它换入内存执行。
3.4 进程控制块PCB
-
PCB(Process Control Block):进程属性的集合
-
OS进程表中包含所有进程的PCB
-
创建新进程时,分配进程表中的一个空闲PCB,填写属性
-
进程终止时回收PCB
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DTKlwUrq-1655605190871)(.\image\PCB访问规则.png)]
-
PCB的属性与典型字段
3.5 执行模式的切换:用户态和系统态
-
CPU有两种执行模式
- 用户态:只能执行非特权指令
- 系统态:也称为核心态、内核态、特权态、控制态、管态。可以执行所有指令(特权指令和非特权指令),使用所有资源以及改变CPU状态
-
两类指令
- 特权指令:在系统态下执行的指令(OS内核使用)
- 非特权指令:用户态下执行(用户程序)
-
执行模式
- 当CPU要执行特权指令时,会引起"陷入trap",即CPU由用户态切换到系统态(称为模式切换),然后去执行OS内核中的一段(特权指令)代码。
-
何时CPU从用户态到系统态?
- 执行系统调用(即内核代码,由OS提供服务)时
- 发生中断或者异常时,执行中断处理程序
-
如何从系统态到用户态?
- 系统调用或中断处理完毕后,执行IRET(中断返回)指令,恢复原进程的PSW,回到用户态
- 中断嵌套时响应另一中断、中断返回在系统态运行时也可以响应中断
3.6 进程切换
- 何时进行进程切换?
- 中断发生时:如时钟中断,当前进程时间片结束,让出CPU,调度新进程,因此发生新旧进程的切换
- 陷阱发生时:当前进程的指令产生错误或错误,非致命时重试或者报告,致命时将结束本进程,调度新进程
- 当前进程执行系统调用时,通常会被阻塞,让出CPU
- 进程切换的步骤
- 保存当前进程的CPU上下文(寄存器现场),更新其PCB;将其PCB转移到相应的就绪或阻塞状态队列
- 选择(调度)另外一个就绪进程,准备执行
- 更新该进程PCB,从就绪队列移出,更新内存管理的数据结构(如设置页表指针、基址/界限寄存器),将该进程的上下文恢复到CPU寄存器中
3.7 fork()
- UNIX中,父进程通过系统调用fork()创建子进程。fork()调用一次,但返回两次,向父进程返回子进程的PID,向子进程返回0
4.第四章
4.1 进程和线程的区别
- 进程:分配资源的单位,不频繁进行切换
- 线程:被调度运行的单位,不拥有资源,可频繁调度切换,轻装运行,也称为轻量级LWP
- 多个线程共享进程空间(内存、文件),通信快
- 子进程空间各自独立,通信时需要借助IPC机制(进程间通信,消息、管道、信号、共享内存区等),慢
- 区别解析
进程
是资源分配和抢占CPU的单位,进程的资源以及地址空间供其所有线程共享
- 线程不拥有系统资源,线程执行环境小,同一进程的不同线程间切换和通信时开销小
- 线程是一个进程内部的
基本调度单位
,一个进程可派生多个线程(执行多条代码流),线程间并发运行
4.2 线程的优点
- 创建/终止一个线程比创建/终止进程的时间要少
- 上下文切换开销少:对进程不频繁地进行切换同一进程内各进程的切换速度快
- 资源共享:进程的资源供其所有线程共享;线程间共享内存,通信方便
- 并发程度高,可利用多处理器结构
4.3 线程的三种状态
- 线程的基本状态:
运行态
、就绪态
、阻塞态
- 挂起/终止一个进程会导致其所有线程被同时挂起/终止
- 与进程类似,多个线程并发执行可以提高系统效率,但需要线程间的同步互斥
4.4 用户级线程和内核级线程的特点
- 线程可分为两类
- 用户级线程(User-Level Thread)
- 内核级线程(Kernel-Level Thread,KLT),也称内核支持的线程、轻量级进程
- 用户级线程
- 用户级线程的创建、撤销、调度与OS内核无关,由用户空间中的线程完成。OS内核并不知道用户级线程的存在,进程各自管理各自的线程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zCoA1FCK-1655605190872)(.\image\进程状态例子.png)]
-
用户级线程的优点
- 一个进程的ULT切换时,不需要切换到系统态
- 进程自己决定如何调度线程,更灵活
- 只要有线程库,用户级线程可以在任何OS上运行,而不需要修改底层的OS代码
-
用户级线程的缺点
- ULT提出阻塞式系统调用时,将阻塞所属进程
- ULT对OS不可见,CPU分配以进程为单位,因此不能利用多CPU结构
-
内核级线程
- 内核级线程的创建、撤销、调度以及同步互斥由OS内核完成,OS通过TCB控制内核级线程
- 对内核级线程的管理类似于进程
- 内核级线程的优点
- 可以同时把一个进程的多个KLT调度到多个CPU上
- 一个KLT阻塞时,OS可调度该进程的另一个KLT
- 内核级线程的缺点
-
用户级线程与内核级线程的对比
|
用户级线程 |
内核级线程 |
调度和切换 |
在一个进程的线程切换,快。以进程为单位分配CPU。不能利用多CPU结构 |
OS管理内核级线程和进程,以内核级线程为单位分配CPU,可以利用多CPU结构 |
当调用阻塞式系统调用时 |
阻塞该用户级线程所属的进程 |
只阻塞内核级线程本身 |
运行时间 |
一个进程内所有用户级线程分享一个时间片 |
每个内核级线程运行一个时间片 |
5.第五章
5.1 互斥的概念
- 当一个进程正在临界区中访问临界资源时,其它进程不能进入临界区
5.2 临界资源与临界区
- 临界资源:一次仅允许一个进程独占使用的不可剥夺资源
- 临界区:进程访问临界资源的那段程序代码。一次仅允许一个进程在临界区中执行
5.3 信号量定义,semWait,semSignal含义
- 信号量:不要求忙等的同步互斥工具,用于进程间传递信号的一个整数值,在信号量上只可进行三种操作,即初始化、递减和增加,这三种操作都是原子操作,递减操作作用于阻塞一个进程,递增操作用于接触一个进程的阻塞,信号量也称为计数信号量或一般信号量
- SemWait(s):本进程请求分配一个资源
- SemSignal(s):本进程释放一个资源
5.4 信号量原语定义
struct semaphore{
int count;/*信号量的值,实际上是可用资源的个数*/
queueType queue;/*因该信号量而阻塞的进程队列*/
/*信号量定义*/
}
semWait(semaphore s){
s.count--;
if(s.count<0){
将当前进程放入s.queue;
阻塞当前进程
}
}
semSignal(semaphore s){
s.count++;
if(s.count<=0){
从s.queue中移除进程P;
将进程P插入到就绪队列;
}
}
5.5 用信号量实现同步与互斥
- 实现互斥
- 对每一临界资源设置一个信号量s,初值=1
- 实现互斥:每个进程在进入临界区之前,执行semWait(s);退出临界区后,执行semSignal(s)
- 临界区内不应有可能引起阻塞或者死锁的因素
const int n = 1;/*进程数*/
semaphore s = 1 ;/*s初值=1*/
void P(int i){
while(true){
semWait(s);
/*临界区代码*/
semSignal(s);
/*其他部分*/
}
}
void main(){
parbegin(P(1),P(2),....P(n));/*n个进程并发*/
}
-
实现同步
- 同步时,对每一类资源设一信号量s,初值>=0,表示可用资源个数
- 资源:可以是同一物理资源的不同状态,如缓冲区的空与满。对空缓冲和满缓冲分别设置信号量
-
要求实现:P1执行过A后,P2才能执行B,设一信号量s,初值为0
-
Process P1:
do
{
....
代码段A
semSignal(s);
}
-
Process P2:
do
{
semWait(s);
代码段B;
...
}
5.6 有限缓冲的生产者/消费者问题
-
生产者/消费者问题介绍
- 一组生产者进程产生数据,放到缓冲区
- 一组消费者进程从缓冲区取出数据使用
- 有限缓冲:假设缓冲池大小固定,包含k个缓冲区,生产者和消费者公用一个循环缓冲池
- 无限缓冲:缓冲数量无限制
-
有限缓冲问题
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FsMFmhDo-1655605190872)(H:\2022年上学期期末复习资料\操作系统\笔记文档\image\优先缓冲模型.png)]
-
一组生产者和进程和一组消费者进程共用一个
-
有sizeofbuffer个缓冲区的缓冲池来交换数据
-
资源、约束条件以及信号量设置
- 互斥:缓冲池一次只能让一个进程访问,设一信号量s,初值为1
- 同步:生产者需要
空缓冲
来发送数据,设一信号量empty,初值为sizeofbuffer
- 同步:消费者需要
满缓冲
来获取数据,设一信号量full,初值为0
-
semaphore mutex = 1;
semaphore empty = sizeofbuffer;
semaphore full = 0;
void producer(){//生产者需要空缓冲
while(true){
semWait(empty);//当获取到空缓冲后,实现同步
semWait(mutex);
/*把数据送到缓冲区*/
semSignal(full);//当缓冲区被填满后,释放满缓冲的信号
semSignal(mutex);//释放临界资源锁
}
}
void consumer(){
while(true){
semWait(full);
semWait(mutex);
/*从缓冲区中取数*/
semSignal(empty);
semSignal(mutex);
/*释放锁的顺序任意*/
}
}
5.7 进程间通过"消息传递"交换信息:无阻塞send和阻塞receive
-
消息传递的原语
-
send(P,message)-给进程P发消息message
-
receive(Q,message)-接收来自进程Q的消息
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kOH3nf6u-1655605190873)(.\image\消息传递模型.png)]
-
同步:发送者发出消息后,接收者才能接收
-
当一个进程执行send()时,该进程可以
- 不阻塞,继续执行
- 被阻塞,直到这个消息被接收者接收
-
当一个进程执行receive()时,该进程可以
- 不阻塞,直到接收已发来的消息或放弃接收,继续执行
- 被阻塞,直到所等待的消息到达
-
无阻塞式send和阻塞式receive最常用
-
send和receive如何指明接收者和发送者
- 直接寻址:指明目标进程或源进程的标识ID,公共服务进程使用receive()时,不指明源进程(隐式)
- 间接寻址:通过信箱发送和接收消息
-
mailBox mayproduce;//空消息邮箱,最初填满空消息,空消息数=空缓冲数,只用于同步
mailBox mayconsume;//用作有界缓冲池,存放消息
-
void producer(){
message pmsg;//存放生产者数据的临时缓冲
while(true){
receive(mayproduce,pmsg);//接收空消息(空缓冲数-1),无空消息时阻塞
pmsg = produce();
send(mayconsume,pmsg);//将pmsg放到有界缓冲池mayconsume中
}
}
-
void consumer(){
message cmsg;
while(true){
receive(mayconsume,cmsg);//阻塞时表示缓冲区全空
consume(cmsg);
send(mayproduce,null);
}
}
6.第六章
6.1 死锁原因:竞争资源、进程推进顺序不当
- 死锁原理:当一组进程中的每个进程都在等待某个事件(所请求的资源被释放),而只有在这组进程中的其他阻塞进程才能触发该事件,称这组进程发生死锁
- 死锁原因
6.2 资源分配图(若死锁,则资源分配图中必有环路,但有环路时不一定死锁)
6.3 死锁的四个必要条件
- 死锁时,四个必要条件同时成立,某一个或几个必要条件成立时并未进入死锁状态
- 互斥:涉及的是需互斥访问的临界资源
- 占有且等待:进程申请资源而阻塞(等待),不释放(继续占有)已分配资源
- 不可抢占:进程已占有的资源未使用完前不可强行剥夺(抢占),只能由进程自愿释放
- 循环等待:进程间形成一个等待资源的循环链
6.4 三种处理方法:预防、避免、检测和恢复
- 死锁预防:破坏四个必要条件之一
- 破坏互斥条件:互斥条件不能被破坏,否则无法保证并发的正确性
- 破坏占用而且等待
- 资源静态分配法:进程运行前,一次性分配所有需要的资源。
若有某个资源不能满足,则全部不分配。
进程等待直至所有资源可用(可能引起进程饥饿,资源利用率低,进程可能事先不知道所需要的资源列表)
- 进程申请新资源被阻塞时,必须主动释放已占用的资源,本进程需要时再重新申请
- OS剥夺低优先级进程的资源给高优先级的进程
- 破坏循环等待条件
- 资源有序分配法:系统内每个资源一个编号,各进程必须严格按照编号递增的顺序申请资源
- 死锁避免:不破坏必要条件,允许进程动态申请资源,但检查资源分配状态,以避免可能导致的死锁
- 进程启动拒绝:如果一个新进程的资源最大需求总量会导致死锁,则不启动此进程
- 当系统的资源总量能够满足"所有进程的最大需求量加上新进程 P n + 1 P_{n+1} Pn+1的最大需求量"时,才启动新进程 P n + 1 P_{n+1} Pn+1
- 资源分配拒绝:如果一个进程提出的某次资源请求会导致死锁,则不允许此次分配
- 死锁检测和恢复:检查系统是否已死锁、哪些进程和资源涉及死锁,并撤销死锁进程或剥夺资源以摆脱死锁
- 只要所请求资源可用,则分配给请求进程,OS定期运行死锁检测算法,判定是否存在死锁
- 解除死锁:代价最小地撤销进程、剥夺资源
- 终止所有死锁进程(最简单)
- 每个死锁进程回滚到某个安全状态的"检查点"(周期性地将内存映像、资源状态写入文件),并重启进程。
- 每次终止一个死锁进程,直到死锁环解除
- 每次剥夺一个资源,直到死锁环彻底解除
- 怎样选择终止进程顺序和剥夺资源的顺序
- 进程已运行时间最少,预计剩余运行时间最长
- 进程已产生的输出最少,已用资源总量最少
- 进程优先级最低,进程是交互式的还是批处理式的
- 防止饥饿:避免总是选择同一个牺牲者(考虑其回滚次数)
- 忽略死锁:假设死锁不会发生
6.5 银行家算法:要求能够判定现在是否安全,某进程请求资源是否能够满足
- 银行家算法(资源分配拒绝):分配资源前,先计算此次分配是否会导致系统处于不安全状态,若安全则分配,否则不分配
- 安全状态:存在一个由所有进程(P1,P2,…,Pn)构成的
安全序列
(如P3、P1、P4、…),如果系统按照这个顺序为每个进程分配所需资源,直至该进程声明的最大资源需求量,则可使每个进程都运行完
- 不安全状态:系统中不存在任何一个安全序列,使得所有进程都能够运行完
- 不安全状态≠死锁状态
- 不安全状态≠死锁不可避免
6.6 用信号量解决不死锁的哲学家问题
6.6.1 哲学家就餐-将发生死锁情形
void phi(int i){//i代表的是当前是第几位哲学家线程在运行,i从0开始
think();
wait(fork[i]);
wait(fork[(i+1)%5]);
//等资源获得完毕后开始就餐
eat();
//释放资源的顺序可以任意
singnal(fork[(i+1)%5]);
singnal(fork[i]);
}
/*当两个哲学家都拿起两把左叉,发生死锁*/
6.6.2 哲学家就餐-使用信号量
/*最多允许四位哲学家拿起左叉*/
semphore room = 4;
semphore fork[5] ={1};//一开始所有资源都是正常的
void phi(int i){
think();
wait(room);//是否得到允许拿左叉,不允许则阻塞
wait(fork[i]);
wait(fork[(i+1)%5]);
eat();
singnal(fork[(i+1)%5]);
singnal(fork[i]);
signal(room);
}
6.6.3 哲学家就餐-对应号数取餐叉
/*奇数号的人先拿左叉,偶数号的人先拿右叉*/
void phi(int i){
think();
if(i%2==1){//奇数号人
wait(fork[i]);
wait(fork[(i+1)%5]);
}else{
wait(fork[(i+1)%5]);
wait(fork[i]);
}
eat();
singal(fork[i]);
singal(fork[(i+1)%5]);
}
7. 第七章
- 内存管理技术:分区(固定/动态分区),分页(简单分页/虚拟内存分页),分段(简单分段/虚拟内存分段)
7.1 固定分区、动态分区策略
- 分区式属于连续分配方式,即为一个用户程序分配一个连续的内存空间
- 将内存划分为若干个分区,每个分区只存放一个进程,各进程只能在它所驻留的分区中运行
- 固定分区:在系统初启时,内存已划分为若干个大小相等或大小不等的分区,并将它们排成一个分区说明表。分区建立后
大小
、边界
、数量
不再改变
- 为进程分配一个满足长度满足要求的最小空闲分区
- 分配回收容易,但限制了进程个数和最大长度,
容易产生(区内)碎片
,内存利用率低
- 动态分区:从可用内存中划出进程所需容量的一块连续区域并分配,其余部分作为一个新空闲区。运行完后回收,若与其他空闲区相邻则合并,
容易产生(区外)碎片
- 首次适配(First Fit)
- 空闲区链表结构:空闲区按
起始地址递增顺序
排列。
- 分配时,从链首开始查找,从第一个满足要求的空闲区中划分出进程需要的大小并且分配,其余部分作为一个新空闲区
- 低地址端遗留许多碎片,高地址端有大空闲区
- 下次适配(Next Fit)
- 空闲区链表结构:空闲区按
起始地址递增顺序
排列
- 分配时,从上次扫描结束处继续查找,从第一个满足要求的空闲区中分配
- 平均查找时间缩短,空闲利用比FF均衡
- 最佳适配(Best Fit)
- 空闲区链表结构:空闲区
按分区大小递增顺序
排列
- 分配时,从链首开始查找,第一个满足要求的空闲区就是满足要求的最小空闲区,划分之
- 链首碎片多,查找费时,回收合并复杂
- 最差适配(Worst Fit)
- 空闲区链表结构:空闲区按
分区大小递减顺序
排列
- 分配时,从链首开始查找,第一个空闲区不能满足要求时分配失败,否则从第一个空闲区中切出需要的大小分配
- 小碎片较少,但最大的空闲区也不会很大
- FF、NF、BF比较:FF最常用
- 内存分配上,FF最快:
不需要调整新空闲区位置
- 内存回收上,FF最佳:
合并空闲区容易
- NF比FF更均衡地利用内存,碎片遍布内存,但使用高地址端的大空闲区很快被划分,压缩次数多
- 查找最合适空闲区时,BF最快,但碎片最多,压缩最频繁。回收,合并相邻空闲区可能要遍历空闲区链表,通常,BF的性能最差
7.2 内部碎片、外部碎片
- 碎片
- 内碎片:所分配的空闲区一般比所要求的空间稍大
- 外碎片:经过一段时间的分配与回收后,内存中存在许多很小的空闲块,由于地址不连续而无法分配
- 通过压缩解决外碎片:
- 向内存的一端移动进程,使碎片在另一端合并成一个大空闲区,费时,需要重新定位
- 为了减少碎片,系统设一最小空闲区长度size,若即将产生的新空闲区小于size,则不再划分,而将整个空闲区分配
7.3 伙伴系统的分配与回收
- UNIXl、Linux采用
伙伴系统
分配内存页框(帧)
- 伙伴:两个相邻的帧块,每块大小必须相同,包含 2 i 2^{i} 2i个帧(i=0,1,2,3,…)。如帧长4KB,
- 帧数1,2,4,8,16,,32,…,尺寸4,8,16,32,64,128KB
- 将更大块的物理内存对半分裂,得到两个伙伴
- 分配:先查找是否有最合适尺寸s的空闲块,若有则分配,如需分配60KB,则s=64KB
- 若没有则查看是否有长为2s的空闲块,仍没有则查找4s,8s,16s…的块,直至找到一个空闲块
- 然后把该块对半分为两个伙伴L和R,R保留作为新空闲块,如果L长为s则直接分配,如果L仍过大,则再次对半分裂为L’和R’,直到得到长为s的左伙伴,将其分配。所有右伙伴都被保留作为新空闲块
- 回收时,如果该左(右)伙伴块的右(左)伙伴块也空闲,则这一对伙伴合并为一大空闲块,合并是递归的,直到没有相邻的空闲伙伴为止
7.4 重定位:将逻辑地址转换为物理地址
- 多道并发环境下,进程被分配到哪个内存区域未知,进程可能需要在磁盘与内存间交换、迁移到另一(未知位置的)内存位置
- 重定位:进程执行过程中,需要将要访问的程序地址转化为实际的内存物理地址
- 逻辑(相对)地址:程序中引用的地址,从0开始顺序编址
- 物理(绝对)地址:数据在内存中的单元地址
7.5 存储保护与越界:基址+界限寄存器
-
进程运行时,动态加载以及重定位
-
存储保护:用两个寄存器标识合法访问地址范围
- 基址+界限:最小合法内存地址+最大合法内存地址
- 基址+限长:最小合法内存地址+地址范围的大小
-
每一进程的这一对值作为现场,保存在各自的PCB中
-
CPU硬件寄存器中是当前进程的值
7.6 分页
7.6.1 基本原理
- 地址位数与所表达的字节数量的关系
- n位地址,可以表达的地址空间为 2 n B 2^nB 2nB
- 帧/页大小L: 2 m 2^m 2mB。512B~16MB,通常为4KB
7.6.2 逻辑地址结构
为进程的多个页离散地分配内存帧。每个进程最后一页有内碎片。无外碎片,内存利用率高
- 逻辑地址A可表示为
页号+页内偏移
- 给定逻辑地址A, p = I N T ( A / L ) , d = A m o d L p=INT(A/L),d=A mod L p=INT(A/L),d=AmodL
7.6.3 页和页框
- 进程的逻辑地址空间划分为同样大小的逻辑块(页面,页Page)
- 内存划分为大小相等的物理块(页框,帧frame)
7.6.4 页表
- 页表:记录进程的每个页存放在哪一个内存帧
- 进程装入内存时,分配帧,并创建页表,进程运行完后,释放帧,销毁页表
- 每个进程有一张自己的页表,页表存于内存
- OS维护一个空闲页框列表
- 位图:每1bit表示一个内存帧状态,0-空闲,1-占用
- 内存帧号i=字号*字长+位号
- 位号=帧号 mod 字长
7.6.5 地址转换
- 页式逻辑地址的划分对程序员透明(不可见):由CPU硬件完成地址转换
- 公式: p = I N T ( A / L ) , d = A m o d L p=INT(A/L),d=A mod L p=INT(A/L),d=AmodL
7.7 分段
7.7.1 基本原理
- 程序的分段结构
- 程序员或编译器将程序按逻辑上有完整意义的段划分,段长不固定,每段有自己的段号,每段都是从0开始编址,共享保护容易
7.7.2 逻辑地址结构
- 32bit逻辑地址:<段号s,段内偏移量d>
- 段式管理的内存分配与释放
- 每段占用一块连续的内存区,各段不必连续
- 无(段内)内碎片,有(段间)外碎片
- 段的分配和回收算法基于动态分区,如FF、NF、BF、WF,回收时相邻空闲区合并
7.7.3 段表
7.7.4 地址转换
- 段式地址转换步骤:逻辑地址->物理地址
- 在段表中查找段号,得到相应段的内存起始地址
- 段内偏移量和该段长度比较,如果
段内偏移量>=段长
则越界,则这个逻辑地址无效
物理地址=段起址+段内偏移量
8. 第八章
8.1 虚拟地址、实地址
- 虚拟地址:也就是逻辑地址,虚拟内存中某字节的地址,仿佛该字节在内存中(其实可能位于磁盘,但对用户透明)
- 实地址:即物理地址,物理内存中某字节的地址
8.2 虚拟分页:基本原理
-
页表结构
- 驻留位(用来标志该页是否在内存中)
- 引用字段:最近被访问次数、距离上次访问的时间间隔
- 修改位:此页装入内存后被修改过(
=1则为脏页
)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tuavQ63l-1655605190873)(H:\2022年上学期期末复习资料\操作系统\笔记文档\image\页表结构.png)]
-
虚拟内存允许进程执行时只将部分程序放入内存,因此程序可以比物理内存要大,用辅助存储器(一般指磁盘)作为内存的补充,虚拟内存的大小受计算机寻址机制和可用的辅助存储器容量限制
,而不受内存容量限制
-
虚拟内存通过OS和硬件MMU(内存管理单元)虚拟出来
-
MMU功能
- 分解逻辑地址
- 逻辑地址到物理地址的转换
- 查找/更新快表
- 进程切换时清空TLB
- 发出缺页中断或者越界中断
- 设置和检测页表中各个特征位
-
虚拟内存的特征
- 进程对代码和数据的引用和访问有集簇倾向,所以虚拟内存方案可行
- 运行进程时只把最近一段时间内要访问的页/段装入内存,其余页/段放在外存,需要时再利用请求调入页/段功能和置换功能将其调入内存
- 从
逻辑上
扩充内存容量
- 访问速度接近于内存,每位(bit)成本接近于外存
-
倒排页表(反置页表)
- 倒排页表为内存的每一页框设置一个页表项
- 内容为该帧所属进程标识和页号
- 理解:在原本的寻址方式中,是通过
内存地址去确定页号
,倒排页表将这一套逻辑翻转,通过页号+进程号
的联合查询来唯一确定一个内存地址(页框号),将该内存地址与偏移组合就形成了新的地址空间
- 哈希优化:对虚拟地址的
用散列函数映射到散列表中,具有相同哈希值的表项被链接在一起,可减少搜索时间
-
CPU必须支持分页或者分段才能实现虚拟内存
-
读取策略
:某一页何时调入内存(请求调入/预调入)
- 请求调入:仅把需要访问的页调入内存
- 预调入:考虑到启动磁盘的寻道和延迟开销,在调入所需页的同时,也调入若干可能马上访问的页面
-
置换策略
:选择哪一页换出内存(FIFO/LRU等)
-
驻留集管理
:给进程分配多少帧(固定的?还是可变的),置换时牺牲谁的帧(全局置换?还是局部置换)
-
清除策略
:何时将脏页写回磁盘(请求清除/预清除)
-
加载控制
:调整系统并发度,防止抖动
8.3 虚拟分页:虚实地址转换
-
虚拟地址< 页号,页内偏移> -> 实地址<页框号,页内偏移>
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lvtjjv1u-1655605190874)(H:\2022年上学期期末复习资料\操作系统\笔记文档\image\虚存分页机制.png)]
-
首先通过页表寄存器找到页表
-
根据虚拟地址中的页号去页表中查找对应的表项
-
查找到表项后就找到页框号
-
将页框号和虚拟地址中的偏移位两者组合就成为内存地址
8.4 缺页中断处理过程
- 缺页中断
- 在一条指令执行期间,当要访问的页不在内存时,产生和处理缺页中断,然后重新执行该指令
- 一条指令的执行可能会引起多次缺页中断
- 图解
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ISiLe5QS-1655605190874)(H:\2022年上学期期末复习资料\操作系统\笔记文档\image\转换过程 .png)]
8.5 转换检测缓冲区TLB(快表)
- 上述页式管理带来的问题
- 每次访问数据都需要访问两次内存
一次访问页表以得到地址,一次根据地址访问以得到数据
- 转换缓冲区
TLB
,也称快表
- 将页表中进程运行最常用的部分放进TLB
- TLB集成到CPU内部的MMU里面。(TLB不同于
Cache
)
- 地址转换时
- 若要访问的页号位于TLB,则从TLB中取出帧号
- 否则,从内存中的页表取出帧号,且添加进TLB
- 当TLB满时,淘汰旧表项,再写入新表项
8.6 虚拟分段和虚拟段页式
-
以段为单位分配内存以及内外存交换。段不等长
-
当发生缺段中断时,可能需要移动或淘汰多个段才能满足新的段需要
-
每个进程一张段表,段表结构如下:
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XXIzgIe3-1655605190875)(H:\2022年上学期期末复习资料\操作系统\笔记文档\image\段表结构.png)]
-
段页式:用户程序划分为段,段再划分为大小相等
的页
-
内存划分为和页同样大小的帧(页框),以帧为单位离散分配内存,每段最后一页有内碎片
,无外碎片
-
逻辑地址结构:段号s+段内页号p+页内地址d
-
每个进程一张段表,每段一张页表
-
固定分区
支持多道程度设计,算法简单,但内碎片多
-
动态分区
无内碎片,但用于外碎片的压缩处理时间长
-
简单页式
克服了碎片多和压缩处理时间长的缺点,但不支持虚拟内存
-
虚存页式
支持虚拟存储,离散分配内存,无外碎片,但不能以自然的方式提供内存的共享和存取保护机制
-
虚存段式
:易于共享和保护,内存碎片多,支持虚拟内存
-
虚存段页式
易于共享和保护,内存碎片少,支持虚拟内存
8.7 虚拟分页的置换算法
- 基于局部性原理,根据进程过去的访问行为预测将来的访问行为,
置换那些(将来)最近一段时间内最不可能访问的页
- 最佳置换算法(OPT,Optimal):淘汰
永不再使用或下次访问距当前时间最长
的页面
- 最近最少使用(LRU,Least Recently Used):淘汰在
最近一段时间内最近未使用
的一页
- 实现:为每页添加"上次访问时间戳",开销大
- 假设:以过去预测将来,最近使用过的页面可能很快被再次使用,很久未用的页可能不会立即使用
- 先进先出(FIFO,First In First out):淘汰
驻留内存最久
的一页
- 实现:将页面按调入内存的时间排成一个队列,每次淘汰队首,性能差
Belady
:通常,帧越多则缺页次数越少,但FIFO算法中,有时,帧越多反而缺页次数越多
- 时钟(Clock)
- 每个页表项设一使用位:页号+帧号+使用位U
- 某进程的所有页面(或整个内存的页框)排成一循环缓冲链;某页被装入或访问时,其使用位U置1
- 置换时顺序查找循环链
- 下次置换时从替换指针处开始查找
- 时钟算法的改进
- 每个页表项设置
使用位U+修改位M
,访问某页时U置为1,被修改时M置为1
- 按照顺序淘汰这四类页面
- U=0,M=0
- U=0,M=1
- U=1,M=0
- U=1,M=1
- 为什么U=0,M=1的页要比U=1,M=0的页优先淘汰?
- U=0,M=1(最近未访问,但曾修改过),在置换时,需要先写回脏页再装入新页,需要2次磁盘I/O
- U=1,M=0(最近访问过,但是干净页),装入新页,再次访问该页时需要再装入,且可能需要置换另一页
- 置换的性能指标还是最近被访问的几率大小
- 缺页性能优劣递减:
OPT->LRU->CLOCK->FIFO
8.8 置换过程以及缺页次数的计算
缺页率 = 不成功访问次数/总访问次数
- 为进程分配主存时
- 每个进程的帧越少,内存中进程就越多,并发度高
- 如果进程只有小部分在内存里,缺页率就会相当高,此时,为进程增加一些内存帧,将显著降低缺页率
- 但分给进程的内存帧超过一定限度后,继续增加帧,也不会明显降低进程的缺页率
- 可接受的缺页率
- 如果缺页率太高,将增加进程帧数
- 如果缺页率太低,将减少进程帧数
8.9 抖动
- 当系统并发度(多道程序度)过高时,缺页频繁,用于调页的时间比进程实际运行的时间还多,CPU利用率极剧下降,此时发生了
抖动
- 原因:所有进程工作集的帧需求总量>内存帧数
- 解决:抖动时,挂起一些进程,释放它们的帧
- 预防抖动
- 在调度程序中引入工作集算法,当各进程的内存驻留级足够大时,才调入新作业
- L=S准则:调度并发度,使得产生缺页的平均时间(即缺页中断之间的平均时间)等于处理一次缺页中断的平均时间
- 50%原则:磁盘利用50%,CPU利用率最高
- 采用局部置换:只在本进程的内存范围内置换
- 当系统并发度较高时,挂起若干进程(如优先级最低的、最年轻的、发生缺页的、占空间最少的、剩余运行时间最长的进程)
9. 第九章
9.1 处理器调度的类型
- 长程调度:新作业提交时,决定是否将其送入内存,成为一个进程,也称作业调度(
作业->进程
:新建态->就绪挂起态
,或新建态->就绪态
)
- 在
批处理系统或者OS的批处理部分
中,新提交的作业放在磁盘的后备作业队列中,长程调度选择某些作业送入内存并创建进程
- 长程调度的时机:根据系统并发度(即多道程序度,内存中进程个数)。当老程序结束或CPU空闲超过阈值时,启动长程调度
- 调度不频繁=>执行速度可以较慢
调度作业的选择
:先来先服务、优先级、预计执行时间、组合CPU密集型和I/O密集型、组合不同I/O需求的作业
- 在
分时系统
中,不需要长程调度,OS总是立即接受用户的交互请求并创建进程,直至系统饱和
- 短程调度:决定将CPU分配给哪个就绪进程(
就绪态进程->运行态进程
)
- 当前运行进程的时间片用完、阻塞、被抢占时、启动短程调度
- 调度频繁(毫秒级)=>执行速度必须很快
- 中程调度:决定把哪些进程在内存与磁盘间进行交换(
就绪挂起
->就绪态
,阻塞挂起
->阻塞
)
系统并发度
决定中程调度时机
- 考虑换入进程和换出进程的内存空间长度
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WtTmEbXs-1655605190875)(H:\2022年上学期期末复习资料\操作系统\笔记文档\image\调度基本类型.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mtjk9Jmf-1655605190875)(H:\2022年上学期期末复习资料\操作系统\笔记文档\image\调度转换图.png)]
9.2 调度准则与指标
- 优先级的使用
- 每个进程有一个
优先级(用优先数表示)
- 调度程序总是优先选择最高优先级队列中的
就绪进程
执行
- 面向用户的性能指标
- 周转时间:从
作业提交
到完成
的时间间隔,包括服务时间(运行态CPU执行)
+等待时间(包括后备态等待进入内存、阻塞态等待资源、就绪态等待CPU)
。适合批处理作业
- 响应时间:从
提交请求到开始响应
。适合分时(交互)系统
- 最后期限:进程完成/开始处理的截止期限。适合
实时交互系统
- 归一化周转时间(带权周转时间): 周 转 时 间 ( 服 务 时 间 + 等 待 时 间 ) / 服 务 时 间 周转时间(服务时间+等待时间)/服务时间 周转时间(服务时间+等待时间)/服务时间
- 面向系统的性能指标
- 吞吐量:
单位时间内完成的进程个数
- 处理器利用率:CPU忙的时间比例=
工作时间/总运行时间
。单用户系统和实时系统不看重该指标
9.3 非抢占式调度、抢占式调度
- 非抢占式:当前进程一直运行,直至其
终止或者阻塞时
,才再次分配CPU
- 抢占式:当其时间片结束或者有更高级进程就绪时,将正运行进程转为就绪,再次分配CPU
9.4 调度算法
9.4.1 先来先服务(FCFS)
- 调度最先进入后备队列/就绪队列的作业/进程,直至运行完或阻塞时,再重新调度
- FCFS通常与优先级策略结合,如每个优先级一条队列,每条队列中的调度基于FCFS原则
- FCFS利于长进程或者CPU密集型的进程,不利于短进程或者I/O密集型进程
9.4.2 轮转(Round Robin)
- 各进程按提交顺序排成就绪队列,然后依次占用处理机,运行完某一时间片,时间片完则排入就绪队列尾
- 时间片的长度:关键参数
- 时间片q太大=>相当于FCFS,响应慢
- 时间片q太小=>上下文切换频繁,开销大
- 时间片q略大于一次典型的交互所需要的时间
- RR的平均周转时间可能更高,但
响应时间更短
- 由于解除阻塞的进程被排入就绪队列队尾,轮转法不利于I/O密集型进程(上次的剩余时间片被浪费)
9.4.3 最短进程优先(Shortest Process Next)
- 调度CPU执行时间预期最短的进程,直至运行完或阻塞时,再重新调度
- 利于短进程而不利于长进程及紧迫任务
9.4.4 最高响应比优先(Highest Response Ratio Next)
- 当前进程完成或阻塞时发生调度,每次调度前计算所有就绪进程的响应比,高者优先
- 实际上,响应比就是一个进程在某一时刻的归一化周转时间
- 响 应 比 R = 周 转 时 间 执 行 时 间 = 等 待 时 间 + 执 行 时 间 执 行 时 间 响应比R = \frac{周转时间}{执行时间} = \frac{等待时间+执行时间}{执行时间} 响应比R=执行时间周转时间=执行时间等待时间+执行时间
9.4.5 最短剩余时间(Shortest Remaining Time)
- 新进程到达时,若新进程的预计运行时间比当前进程的剩余运行时间更短,则抢占当前进程
9.4.6 反馈(多级反馈队列)Multilevel Feedback
- 基于时间片的抢占+动态优先级调度
- 设立多个就绪队列,优先级越高的队列,其时间片越小
- 同一队列内进程按
FCFS
调度,但末级队列按照轮转法
调度
- 当进程在一个时间片内未运行完,则降到下一级队列末尾
- 当上级队列均为进程就绪时,才调度本级队列内进程
- 实用,能较好地满足交互型进程,短进程,长进程的要求
9.4.7 优先级调度
- 调度优先级最高的进程。就绪队列中进程按优先级递减排列,每次调度最高级队列的队首程序
- 可抢占:新进程的高级进程立即抢占当前进程
- 不可抢占:当前进程继续运行,新到达的高级进程按照其优先级,进入到合适的就绪队列
- 优先静态权:创建进程时确定优先级,保持不变
- 动态优先权:创建进程时赋予一个优先权初值,但随着进程的等待时间延长,其优先级会升高(称为老化Aging),随着CPU执行时间的延长,其优先级会降低
10.第十章
10.1 多处理器系统中的调度算法
FCFS
算法
静态优先级+FCFS
算法
- 双处理器下,不同调度算法所导致的吞吐量(单位时间内完成的作业个数)差别很小
10.2 实时任务分类
硬实时任务
:必须在最后期限内开始或完成
软实时任务
:时间限制较弱
非周期性实时任务
:不定期发生
周期性实时任务
:每隔T个时间单位发生一次
11.第十一章
11.1 程序控制I/O
11.2 中断驱动I/O
- 中断驱动I/O:各种设备通用,中断次数多,CPU负担重
- 设备每I/O完一批字(设备控制器的数据缓冲区长度)后,以中断请求方式通知CPU,再由CPU把这些字送入内存,然后设备再I/O下一批字
- 中断可以使I/O设备之间、I/O设备与CPU之间并行操作,但中断种类和次数太多时,CPU负担重
11.3 直接存储访问器DMA与I/O过程
直接存储器访问DMA
:速度快,数据量大,在完成一个数据块的I/O之后,向CPU发出一次中断,中断次数少,适合于磁盘、网络接口等的I/O
- 在内存和设备间直接进行块传送,仅在传送开始和结束时才需要CPU的干预,整块数据的传送是在DMA控制器的控制下完成的
通过窃取总线周期
:在争用总线时,DMA控制器的优先级比CPU要高
- DMA控制器
- DMA工作原理与过程
- CPU向DMA控制器发出I/O数据块的指令
<读/写操作、源/目的地址、传送字(节)数>
- 发出数据传送请求的进程阻塞,CPU调度其它程序
- 由DMA控制器完成设备的一个连续数据块与一个连续内存区之间的直接传送(不断地抢占总线挪用CPU工作周期,将缓冲中的数据写入内存单元,或从内存单元读出写到缓冲),传送字(节)递减到0
- 一个数据块I/O完后,DMA控制器向CPU发出中断
- 发出数据传送请求的进程被唤醒
- I/O效率高,DMA传送时,CPU执行效率略微降低
11.4 缓冲buffer的主要作用
缓冲buffer
:在设备间或设备与程序间传输时,用来保护数据的内存区域与设备专用缓冲
内存公用缓冲池
由OS划分、分配、回收、管理
设备的专用缓冲
由设备控制器管理
- 缓和CPU与I/O设备间
速度不匹配的矛盾
,提高并行性
- 协调设备
数据大小差异(如逻辑记录与磁盘块大小不一致)
减少对CPU的中断频率,放宽响应时间限制
11.5 磁盘访问时间
- 扇区是
最小寻址单位和存取单位(但不是分配单位)
- 分配磁盘空间时以
盘块(簇)
为单位,1盘块 =2^n扇区
- 由内磁道向外的位密度要不断降低
- 磁头由外向内时,驱动器要加速
磁盘访问时间包含以下三部分
T a = T s + T r + T t T_a= T_s+T_r+T_t Ta=Ts+Tr+Tt
- 寻道时间Ts =
启动磁盘时间
+横跨n条磁道时间
- 旋转延迟时间Tr =
将待访问扇区转到磁头下的时间
- 若15000r/min,则每转4ms(
60/15000=0.004
),Tr平均2ms
- 传输时间Tt
- T t = 读 写 字 节 数 b 旋 转 速 度 r ∗ 每 磁 道 字 节 数 N T_t = \frac{读写字节数b}{旋转速度r*每磁道字节数N} Tt=旋转速度r∗每磁道字节数N读写字节数b
- 已知
每转4ms,每磁道500扇区,每扇区需要4/500=0.008ms
11.6 磁盘调度算法
磁盘调度
:调整多个磁盘访问请求的服务顺序,以降低平均磁盘服务时间
,减少的是磁头移动距离(寻道时间)
11.6.1 先进先出(FIFO,First In First Out)
- 按
请求的接受顺序
服务
LIFO
:先处理最新提出的请求。事务处理时,读取文件具有局部性
,LIFO可减少,磁臂移动,提高吞吐量,但先提出的请求会饥饿
11.6.2 最短服务时间优先(SSTF,Shortest Service Time First)
- 也称
最短寻道时间优先算法
,优先选择距离当前磁头位置最近的访问请求进行服务
- 可能造成某些访问请求长期等待而
饥饿
,特别是磁头附近不断地到达新请求时
11.6.3 SCAN(扫描算法)
SCAN扫描算法
:也称电梯算法,选择位于磁头移动方向前方
,而且距离磁头位置最近的访问进行服务。当前方没有访问请求时,立即改变磁头移动方向(LOOK
),或继续扫描到磁盘边界后再转向
电梯LOOK
被普遍采用,是对SCAN的改进,SCAN偏爱靠近磁盘边界处的请求,对最近横跨过的区域不公平
11.6.4 C-SCAN(循环扫描算法)
C-SCAN
循环扫描算法:磁头从磁盘一端移动到另一端,随着移动而不断处理请求,当磁头移到另一端时,马上返回磁盘起始,返回的过程不处理请求
- 适合磁盘负荷大的系统
11.7 RAID的核心技术
RAID
用多个小容量磁盘代替单个大容量磁盘。
- 优势:
增加
数据容量,多个磁盘并行I/O可提高速度,设置冗余磁盘可提高可靠性
- RAID是一组磁盘阵列,但OS视其为一个整体
- 数据以
条带化
方式存储在磁盘阵列中
- 除了数据盘之外,另有冗余磁盘保存(奇偶)校验信息,作为校验盘,在某个磁盘失效时用于恢复数据
11.7.1 磁盘条带化
- 将
N个(一组)
磁盘看作是一个存储部件,将每个数据盘块划分为几个子块(条带),把每个子块的数据分别存储到各个不同磁盘的相同位置上
11.7.2 并行访问
- 读写时,
N个
磁盘并行地读写各个子块。磁盘传输率提高了N-1
倍
11.7.3 块交叉检验
- 在磁盘条带化的基础上,在每组磁盘中设置一个校验盘,该盘上任一位的内容为组中所有数据盘同一位的校验
- 在写组中任一数据盘的任一块时,都要计算新的校验并写入校验盘相同块
- 当一个数据盘出故障时,可以根据其余数据盘和校验盘的内容,计算并恢复故障盘内容
11.7.4 RAID 0
无冗余的并行访问
:仅仅是将磁盘条带化而实现并行访问
,只实现条带化和并行访问,容量大,块,但不容错
11.7.5 RAID 1
可并行访问的镜像磁盘(复制每个磁盘)
:容量大,快,可靠,但磁盘数太多
12. 第十二章
12.1 树型目录,文件共享
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OSY1Ympk-1655605190876)(H:\2022年上学期期末复习资料\操作系统\笔记文档\image\目录树.png)]
- 文件共享
- 对一个文件的访问权限层次:
无权限
、知道该文件存在
、执行
、读
、在文件尾追加
、写
、更改其他用户的访问权限
、删除文件
- 创建文件的用户是文件所有者,拥有全部权限。可向其他用户授予权限
- 同时访问
- 多个用户可以同时读文件
- 用户在修改文件时,对整个文件或相关记录加锁,实现互斥写。防止死锁
12.2 三种文件的分配方式
- 磁盘I/O以"块"(如扇区)为单位,字节流式文件可直接I/O,但记录式文件需将多条记录组装成块才能I/O
固定组块
:记录长度固定,若干完整的记录放在一块,块后部可能有内碎片
可变长度跨越式组块
:记录长度可变,尽量占满一块。有些记录可能跨越两块
可变长度非跨越式组块
:记录长度可变,但不哭跨块,有块内碎片,一条记录的长度不能超过块尺寸
12.2.1 连续分配
- 为每个文件分配一组相邻的盘块(FF,BF,WF)
- 文件属性清单:(起始块号,块数)
- 顺序访问和随机访问都方便;寻道少,I/O快
- 磁盘外碎片多,需紧缩,文件不能动态增长
12.2.2 链接分配
- 每个盘块有一链接指针,将该文件的多个离散的盘块链接成一个链表。
- 动态分配的,没有外碎片,寻道多,I/O慢,适合顺序访问,随机访问困难
12.2.3 索引分配
- 把所有盘块的地址集中到索引块中
- 没有外碎片;随机访问;但增加索引块的开销
- 基于单个索引盘块进行索引分配:索引块中包含所有块号,增加或删除一块时修改索引表即可
- 基于长度可变的盘块分区进行索引分配:同样一个索引块的开销,可为文件分配更多盘块
12.3 索引分配对文件尺寸的影响
如果磁盘块长4KB(即索引块和数据块均长4KB),每个盘块指针4B,则采用基于单个盘块的索引分配时允许的文件最大尺寸是多少?
计算索引块能引出多少个块
: 4KB/4B
= 1K个指针
文件的最大尺寸 = 4KB*1K = 4K^2B=4MB
基于大小可变的分区的索引分配,假设索引块中“长度” 域占1B、2B,文件最大尺寸分别是多少?
当长度为1B
:则盘块指针长度为5B,则有4KB/5B = 819个指针
,一个指针指向一个连续盘块区,每区最多有(2^8-1=255个盘块)文件最大尺寸为819*255*4KB=815.8MB
当长度为2B
:则盘块指针长度为6B,则有4KB/6B = 682个指针
,每区最多有(2^16)-1=64K个盘块
,文件最大尺寸为682*64K*4KB=170.5GB
12.4 磁盘空闲管理(位图)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dLJuGqSk-1655605190876)(H:\2022年上学期期末复习资料\操作系统\笔记文档\image\磁盘管理位图.png)]
12.5 UNIX中的文件控制块(索引节点i-node)
- UNIX中的文件控制块:索引节点 i-node。
- 创建文件时,在磁盘上建立一个磁盘i-node。
- 文件名和
i-node
号保存在目录项中
- 除文件名外,所有其它属性都保存在 i-node 中。
- 目录文件中存储的是唯一的文件名,文件名后还有一个2B的域用来存储i-node在i-node表的地址
12.2 三种文件的分配方式
- 磁盘I/O以"块"(如扇区)为单位,字节流式文件可直接I/O,但记录式文件需将多条记录组装成块才能I/O
固定组块
:记录长度固定,若干完整的记录放在一块,块后部可能有内碎片
可变长度跨越式组块
:记录长度可变,尽量占满一块。有些记录可能跨越两块
可变长度非跨越式组块
:记录长度可变,但不哭跨块,有块内碎片,一条记录的长度不能超过块尺寸
12.2.1 连续分配
- 为每个文件分配一组相邻的盘块(FF,BF,WF)
- 文件属性清单:(起始块号,块数)
- 顺序访问和随机访问都方便;寻道少,I/O快
- 磁盘外碎片多,需紧缩,文件不能动态增长
12.2.2 链接分配
- 每个盘块有一链接指针,将该文件的多个离散的盘块链接成一个链表。
- 动态分配的,没有外碎片,寻道多,I/O慢,适合顺序访问,随机访问困难
12.2.3 索引分配
- 把所有盘块的地址集中到索引块中
- 没有外碎片;随机访问;但增加索引块的开销
- 基于单个索引盘块进行索引分配:索引块中包含所有块号,增加或删除一块时修改索引表即可
- 基于长度可变的盘块分区进行索引分配:同样一个索引块的开销,可为文件分配更多盘块
12.3 索引分配对文件尺寸的影响
如果磁盘块长4KB(即索引块和数据块均长4KB),每个盘块指针4B,则采用基于单个盘块的索引分配时允许的文件最大尺寸是多少?
计算索引块能引出多少个块
: 4KB/4B
= 1K个指针
文件的最大尺寸 = 4KB*1K = 4K^2B=4MB
基于大小可变的分区的索引分配,假设索引块中“长度” 域占1B、2B,文件最大尺寸分别是多少?
当长度为1B
:则盘块指针长度为5B,则有4KB/5B = 819个指针
,一个指针指向一个连续盘块区,每区最多有(2^8-1=255个盘块)文件最大尺寸为819*255*4KB=815.8MB
当长度为2B
:则盘块指针长度为6B,则有4KB/6B = 682个指针
,每区最多有(2^16)-1=64K个盘块
,文件最大尺寸为682*64K*4KB=170.5GB
12.4 磁盘空闲管理(位图)
[外链图片转存中…(img-dLJuGqSk-1655605190876)]
12.5 UNIX中的文件控制块(索引节点i-node)
- UNIX中的文件控制块:索引节点 i-node。
- 创建文件时,在磁盘上建立一个磁盘i-node。
- 文件名和
i-node
号保存在目录项中
- 除文件名外,所有其它属性都保存在 i-node 中。
- 目录文件中存储的是唯一的文件名,文件名后还有一个2B的域用来存储i-node在i-node表的地址