3. 处理机调度
3.1 处理机调度的层次和目标
层次
- 高级调度(High Level Scheduling):调度对象是作业。根据某种算法,决定将外存处于后备队列中的哪几个作业调入内存。只用于多道批处理系统中。
- 中级调度(Intermediate Scheduling):将那些暂时不能允许的进程,调至外存等待;当它们具备运行条件且内存又稍有空闲时,由中级调度来讲外存上的那些具备允许条件的就绪进程重新调入内存。
- 低级调度(Low Level Scheduling):调度对象是进程(或内核级线程)。根据某种算法,决定就绪队列中的哪个进程获得处理机,并由分派程序将处理及分配给选中的进程。
目标
- 资源利用率( Utilization )
- 公平性(Fairness)
- 资源的平衡利用(Balance)
- 策略的强制执行
3.2 作业调度
一些基本概念
周转时间 = 作业完成时刻 - 作业到达时刻
带权周转时间 = 周转时间 / 服务时间;
平均周转时间 = 作业周转总时间 / 作业个数;
平均带权周转时间 = 带权周转总时间 / 作业个数;
先来先服务(First-come First-Served,FCFS)调度算法
该算法既可用于作业调度,也可以用于进程调度。系统按照作业到达的先后次序来进行调度
短作业优先(Shortest Job First,SJF)调度算法
该算法既可以用于作业调度,又可以用于进程调度。 在作业调度中,该算法每次从后备作业队列中挑选估计服务时间最短的一个或几个作业,将他们调入内存,分配必要的资源,创建进程并放入就绪队列。
最短剩余时间优先(Shortest Remaining Time,SRT)调度算法
抢占式算法,最短剩余时间优先,总是选择剩余时间最短的进程。
优先级调度算法(Priority-Scheduling Algorithm,PSA)
由外部赋予作业相应的优先级,系统从后备队列中选择若干个优先级最高的作业装入内存。
高响应比优先级调度算法(Highest Response Ratio Next,HRRN)
高响应比优先调度算法既考虑作业的执行时间也考虑作业的等待时间,综合了先来先服务和最短作业优先两种算法的特点。
该算法中的响应比是指作业等待时间与运行比值,响应比公式定义如下:
响应比 =(等待时间+要求服务时间)/ 要求服务时间,即 RR =(w+s)/ s= 1 + w / s,因此响应比一定是大于 1 的。
系统把处理机分配给就绪队列中响应比最高的进程。
例子
分别算出用 FCFS、SJF、HRRN 调度的周转时间、带权周转时间、平均周转时间、平均带权周转时间。
作业名 | 到达时间 | 处理时间 |
---|---|---|
A | 0 | 3 |
B | 2 | 6 |
C | 4 | 4 |
D | 6 | 5 |
E | 8 | 2 |
FCFS:
作业名 | 开始时间 | 结束时间 | 周转时间 | 带权周转时间 |
---|---|---|---|---|
A | 0 | 3 | 3 | 1 |
B | 3 | 9 | 7 | 1.5 |
C | 9 | 13 | 9 | 2.25 |
D | 13 | 18 | 12 | 2.4 |
E | 18 | 20 | 12 | 6 |
总周转时间:43
总带权周转时间:13.15
SJF:
作业名 | 开始时间 | 结束时间 | 周转时间 | 带权周转时间 |
---|---|---|---|---|
A | 0 | 3 | 3 | 1 |
B | 3 | 9 | 7 | 1.5 |
C | 11 | 15 | 11 | 2.75 |
D | 15 | 20 | 14 | 2.8 |
E | 9 | 11 | 3 | 1.5 |
总周转时间:38
总带权周转时间:9.95
HRRN:
作业名 | 开始时间 | 结束时间 | 周转时间 | 带权周转时间 |
---|---|---|---|---|
A | 0 | 3 | 3 | 1 |
B | 3 | 9 | 7 | 1.5 |
C | 9 | 13 | 9 | 2.25 |
D | 15 | 20 | 14 | 2.8 |
E | 13 | 15 | 7 | 3.5 |
总周转时间:40
总带权周转时间:11.05
所以
算法 | 平均周转时间 | 平均带权周转时间 |
---|---|---|
FCFS | 8.6 | 2.63 |
SJF | 7.6 | 1.99 |
HRRN | 8 | 2.21 |
3.3 进程调度
任务
- 保存处理机的现场信息
- 按某种算法选取进程
- 把处理机分配给进程
方式
- 非抢占式(Nonpreemptive Mode):把处理机分配给某进程后,就一直让其运行下去,除非发生某时间被阻塞时,才把处理机分配给其他进程
- 抢占式(Preemptive Mode):允许调度程序根据某种原则, 去暂停某个正在执行的进程,将分配给原进程的处理机分配给其他进程。主要遵循原则:
- 优先权原则
- 短进程优先原则
- 时间片原则
轮转调度算法
根据 FCFS 策略,将所有就绪进程排列成队列,每个进程每次仅运行一个时间片。
优先级调度算法
优先级调度算法类型:
- 非抢占式
- 抢占式
优先级类型:
- 静态优先级
- 动态优先级
多队列调度算法
多级反馈队列(Multileved Feedback Queue)调度算法
基于公平原则的调度算法
3.4 实时调度
最早截止时间优先 EDF(Earliest Deadline First)算法
根据截止时间确定优先级,截止时间越早, 优先级越高。该算法既可用于抢占式,也可以用于非抢占式。
最低松弛度优先 LLF(Least Laxity First)算法
根据松弛度来确定任务优先级。
松弛度 = 必须完成时间 - 本身运行时间 - 当前时间
3.5 死锁
定义
一组进程中每个进程都无限等待被该组进程中另一进程所占有的资源而处于的一种僵持局面,若无外力作用,它们都无法向前推进,这种现象称为进程死锁(Deadlock),这组进程就称为死锁进程。
必要条件
- 互斥条件:一段时间内,某资源只能被一个进程占用
- 请求和保持条件:进程已经保持了至少一个资源,但又提出新的资源请求,但该资源已被其他进程占用
- 不可抢占条件:进程已获得资源在未使用完之前不能被抢占,只能在进程使用完后自己释放
- 循环等待条件:进程-资源的循环链,即进程集合{p0,p1,p2,……,pn}中的p0正在等待一个 p1 所占用的资源,p1 正在等待 p2 占用的资源,……,而 pn在等待 p0 所占用的资源
预防死锁
- 破坏“请求和保持”条件
- 破坏“不可抢占”条件
- 破坏“循环等待”条件
避免死锁
银行家算法
最具代表性的避免死锁算法就是 Dijkstra 的银行家算法:在每一个新进程在进入系统时,它必须申明在运行过程中,可能需要每种资源类型的最大单元数目,其数目不应超过系统所拥有的资源总量。当进程请求另一组资源时,系统必须首先确定是否有足够的资源分配给该进程。若有,再进一步计算在将这些资源分配给进程后,是否会使得系统处于不安全的状态。如果不会,才将资源分配给它,否则让进程等待。
数据结构
实现银行家算法,需要设置四个数据结构
- 可利用资源向量 Avaiable
- 最大需求矩阵 Max
- 分配矩阵 Allocation
- 需求矩阵 Need
银行家算法流程
安全性算法
为进行安全性检查,定义数据结构:
- Work : ARRAY[0..m-1] of integer;
- Finish : ARRAY[0..n-1] of Boolean;
其中 m 代表资源种类数,n 代表进程的数量;Work表示系统可提供给进程继续运行的各类资源的数目;Finish表示系统是否有足够的资源分配给该进程。
例子
设系统有五个进程和三类资源,每类资源分别共有10、5、7。此时可以找到一个安全序列<P1, P3, P0, P2, P4>
,系统是安全的。
练习
有三类资源 A(17)、B(5)、C(20)。有5个进程 P1~P5。T0 时刻系统状态如下:
进程 | 最大需求 | 已分配 |
---|---|---|
P1 | 5 5 9 | 2 1 2 |
P2 | 5 3 6 | 4 0 2 |
P3 | 4 0 11 | 4 0 5 |
P4 | 4 2 5 | 2 0 4 |
P5 | 4 2 4 | 3 1 4 |
问:
- T0 时刻是否为安全状态,给出安全系列。
- T0 时刻,P2: Request(0,3,4),能否分配,为什么?
- 在 (2) 的基础上P4:Request(2,0,1),能否分配,为什么?
- 在 (3) 的基础上P1:Request(0,2,0),能否分配,为什么?
解答:
- 先求出 Need 矩阵和 Work 数组:
进程 | Need |
---|---|
P1 | 3 4 7 |
P2 | 1 3 4 |
P3 | 0 0 6 |
P4 | 2 2 1 |
P5 | 1 1 0 |
Work 此时为:2 3 3
进程 | Work | Allocation | Need | W+A | Finish |
---|---|---|---|---|---|
P5 | 2 3 3 | 3 1 4 | 1 1 0 | 5 4 7 | T |
P4 | 5 4 7 | 2 0 4 | 2 2 1 | 7 4 11 | T |
P3 | 7 4 11 | 4 0 5 | 0 0 6 | 11 4 16 | T |
P2 | 11 4 16 | 4 0 2 | 1 3 4 | 15 4 18 | T |
P1 | 15 4 18 | 2 1 2 | 3 4 7 | 17 5 20 | T |
此时处于安全状态。
- 因Available (2 3 3) < Request (0,3,4),所以不能分配
- P4:Request (2,0,1),分配之后变为Available(0,3,2),此时执行安全性算法:
Work | Allocation | Need | W+A | Finish |
---|---|---|---|---|
P4 | 0 3 2 | 4 0 5 | 0 2 0 | 4 3 7 |
P5 | 4 3 7 | 3 1 4 | 1 1 0 | 7 4 11 |
P3 | 7 4 11 | 4 0 5 | 0 0 6 | 11 4 16 |
P2 | 11 4 16 | 4 0 2 | 1 3 4 | 15 4 18 |
P1 | 15 4 18 | 2 1 2 | 3 4 7 | 17 5 20 |
4. P1:Request(0,2,0),分配之后变为Available(0,1,2),此时执行安全性算法:
Allocation | Need | Available |
---|---|---|
P1 | 2 3 2 | 3 2 7 |
P2 | 4 0 2 | 1 3 4 |
P3 | 4 0 5 | 0 0 6 |
P4 | 4 0 5 | 0 2 0 |
P5 | 3 1 4 | 1 1 0 |
但 Available(0,1,2)已经无法满足任何进程的需要,不能分配。
死锁的检测与解除
资源分配图
如果资源分配图中没有环路,则系统中没有死锁。如果图中存在环路则系统中可能存在死锁。
如果每个资源类中只包含一个资源实例,则环路是死锁存在的充分必要条件。
有环无死锁
有环有死锁
4. 存储器管理
4.1 存储器的层次结构
4.2 程序的装入与链接
用户源程序执行通常要经过的步骤:
- 编译,由编译程序(Compiler)将用户源代码编译成若干个目标模块(Object Model)。
- 链接,由链接程序(Linker)将编译后形成的目标模块以及它们所需要的库函数,链接在一起,形成一个装入模块(Load Module)。
- 装入,由装入程序(Loader)将装入模块装入主存的过程。
程序的装入
把程序装入内存空间。采用三种方式:
绝对装入方式(Absolute Loading Mode):在可执行文件中记录内存地址,装入时直接定位在上述(即文件中记录的地址)内存地址。
优点:
- 装入过程简单。
缺点:
- 过于依赖于硬件结构,不适于多道程序系统。
可重定位方式(Relocation Loading Mode):在可执行文件中,列出各个需要重定位的地址单元和相对地址值。当用户程序被装入内存时,一次性实现逻辑地址到物理地址的转换,以后不再转换。
优点:
- 不依赖于硬件,可以装入有限多道程序。
缺点:
- 一次性全部装入;
- 一个程序通常需要占用连续的内存空间;
- 程序装入内存后运行时不能移动。
动态运行时装入方式(Dynamic Run-time Loading):在装入模块装入主存后,并不立即把装入模块中的相对地址转换为绝对地址, 而是把这种地址转换推迟到程序要真正执行时才进行。实现时需要重定位寄存器。
优点:
- 不需要一次装入;
- OS可以将一个程序分散存放于不连续的内存空间,可以移动程序。
- 能够支持程序执行中产生的地址引用,如指针变量。
- 它是虚拟存储的基础。
缺点:
- 需要硬件支持,OS实现较复杂。
程序的链接
链接程序的功能是将经过编译或汇编后所得到的一组目标模块以及它们所需要的库函数,装配成一个完整的装入模块。
实现链接的方法有三种:
- 静态链接(Static Linking):事先进行链接以后不再拆开的链接方式
- 装入时动态链接(Load-time Dynamic Linking):用户源程序经编译后所得到的目标模块,是在装入主存时,边装入边链接的。
- 运行时动态链接(Run-time Dynamic Linking):可将某些目标模块的链接,推迟到执行时才进行。
4.3 连续分配存储管理方式
连续分配方式是指为一个用户程序分配一个连续的内存空间。
单一连续分配
内存分为两个区域:系统区、用户区。应用程序装入到用户区,可使用用户区全部空间。最简单,适用于单用户、单任务的OS。
优点:
- 易于管理。
缺点:
- 对要求内存空间少的程序,造成内存浪费
- 程序全部装入,很少使用的程序部分也占用内存。
固定分区分配
固定分区就是把内存划分为个数固定、大小相等或不等的多个区域。分区的划分由计算机的操作员或者由操作系统给出,并给出分区说明表。
早期IBM的OS/360 MFT(具有固定任务数的多道程序系统)采用了这种固定分区的方法。
在作业大小和出现频率均已知的情况下,固定分区是合适的。在这种情况下分区的大小选择与作业大小相当,这样内存的使用效率较高。但是若作业的大小和出现的频率不知道时,势必造成分区的大小和作业的大小相差甚远,这样就会造成存储空间的浪费,从而影响整个系统的效率。可以和覆盖、交换技术配合使用。
优点:
- 易于实现,开销小。
缺点:
- 内存碎片(零头)造成浪费
- 分区总数固定,限制了并发执行的程序数目。
动态分区分配
动态分区分配是指在系统运行的过程中建立分区,并使分区的大小刚好与作业的大小相等。这种存储管理的方法解决了固定分区严重浪费内存的问题。是一种较为实用的存储管理方法。
在动态分区存储管理中,要有相应的数据结构来登记空闲分区的信息,它包括空闲分区的大小和位置。
不同系统根据设计要求采用不同的结构。常用的有空闲分区表和空闲分区队列结构。
系统还要设置等待分区队列,当系统中无空闲区或无满足要求的空闲区时,则把申请者送入等待队列中,等待别的进程释放内存之后再唤醒队列中的进程。
分配策略
- 首次适应法(first fit,FF):要求空闲分区按首址递增的次序组织空闲分区表(队列)。 倾向于优先使用内存中低址的空闲分区。但可能会造成低址部分不断被划分,留下许多难以利用的空间碎片。
- 循环首次适应算法(next fit,NF):按分区的先后次序,从上次分配的分区的下一个空闲分区开始查找(到最后分区时再回到开头),找到符合要求的第一个分区。该算法的分配和释放使空闲分区分布更均匀,但较大的空闲分区不易保留。
- 最佳适应法(best fit,BF):要求空闲分区按大小递增的次序组成空闲分区表(队列)。系统从表头开始查找,当找到第一个满足要求的空闲区时,停止查找,并且这个空闲区是最佳的空闲区。分配和回收后要对空闲区表(队列)重新排序。每次分配后所切割下的空闲区一般情况下是很小的,以致无法使用,造成很多难以利用的碎片。
- 最坏适应法(worst fit,WF):要求空闲分区按大小递减的次序组成空闲分区表(队列)。系统总是挑选一个最大的空闲分区,从中分割一部分给作业使用。但其未必是最坏的,当程序装入内存中最大的空闲区后,剩 下的空闲区还可能相当大,还能装下较大的程序。而且每次仅作一次查询工作。
策略比较
上述三种放置策略各有利弊,到底哪种最好不能一概而论,而应针对具体作业序列来分析。对于某一作业序列来说,某种算法能将该作业序列中所有作业安置完毕,那么该算法对这一作业序列是合适的。对于某一算法而言,如它不能立即满足某一要求,而其它算法却可以满足此要求,则这一算法对该作业序列是不合适的。
例子
- 有作业序列:作业A要求18K;作业B要求25K,作业C要求30K。系统中空闲区按三种算法组成的空闲区队列:
问,哪个算法是最适合这个作业序列:
最佳适应法对这个作业序列是合适的,而其它两种对该作业序列是不合适的。
2.有作业序列:作业A要求21K;作业B要求30K,作业C要求25K。系统空闲区:
最坏适应法对这个作业序列是合适的,而其它两种对该作业序列是不合适的。
可重定位分区分配
4.4 分页存储管理
在分区存储管理中,不论采用什么办法都会出现碎片问题,从而降低了内存的利用率。虽然采用压缩存储区的方法可以解决碎片问题,但系统开销太大,而无实用价值,必须寻求新的技术来解决这一问题,于是分页技术产生了。分页技术是由曼彻斯特大学提出,并于1960年前后在Atlas计算机上实现。这种技术对OS的发展产生了深远影响。
用户程序
把用户程序按逻辑页划分成大小相等的部分,称为页(page),从 0 开始编页号,页内地址是相对于 0 编址。一般一页的大小为 2 的整数次幂。地址的高位部分为页号,低位部分为页内地址。分页技术可以减少碎片的产生,但进程的最后一页仍然会产生碎片。
内存空间
按页的大小将内存空间划分为大小相等的区域,称为块或内存块(物理页面,页框)。
内存分配
以页为单位进行分配,并按作业的页数多少来分配。逻辑上相邻的页,物理上不一定相邻。
页表
若将应用程序的包含页号和页内地址的逻辑地址转换成内存地址,必须要有一个数据结构,用来登记页号和块号的对应关系和有关信息。这样的数据结构称为页表。系统为每个进程在内存建立一个页表。
页表内容:
页号:登记程序地址空间的页号
块号:登记相应的页所对应的内存块号
其它:登记与存储信息保护有关的信息
例如:
页号 | 块号 | 其它 |
---|---|---|
0 | 5 | … |
1 | 65 | … |
2 | 13 | … |
映射图
例图 1
例图 2
作业 1 有 2 页分别装入内存的第 5、6 块;作业2有3页装入内存的第2、4、7块;作业3 有 1 页装入内存的第 8 块:
页地址映射
分页中的地址映射其实与通常的地址映射的概念是一样的,即把程序地址转换成内存地址,这个转换过程是在程序执行过程中完成的,是动态地址映射。在现代计算机系统中,由系统提供的地址映射硬件来完成地址映射工作。
例子
设页长为1K,程序地址字长为16位。
在执行指令 MOV r1,[2500]
时,地址转换步骤:
取出程序地址字 2500 送虚地址寄存器 VR;
由 MMU 硬件分离出页号 P 和页内地址 W;因为页长为 1K,所以页内地址占 10 位(0-9位),页号占 6 位(10-15位);硬件取出VR寄存器中的高 6 位即为页号,低 10 位即为页内地址。
- 计算可得页号 P=2,页内偏移 W=2500 - 2048 = 452
- 根据页号 P=2,硬件自动查该进程的页表,找到第 2 页对应的块号为 7,将块号送到内存地址寄存器MR的高 6 位中。将 VR 中的 W 的值 452 复制到 MR 的低 10 位中,从而形成内存地址。系统就以 MR 中的地址访问内存。
计算方法
若给出的地址为 16 进制,则将其转换为二进制,然后,根据页长及程序地址字的长度,分别取出程序地址的高 几位和低 几 位就得到页号及页内地址。如页长为 2K,程序地址字为 16 位,则高 5 位为页号,低 11 位为页内地址。
若给出的地址为 10 进制,则通过,程序地址/页长
,商即为页号,而余数为页内地址。例如:程序地址为 8457, 页长为 4KB,则页号为:8457/4096=2页;而偏移量为:8457 % 4096 = 256。
信息保护
分页存储管理中的信息保护从两个方面来实现:
在分离程序地址的页号和页内地址时判别访问是否合法,用于越界保护。若产生的页号满足下式为合法:
0 <=页号 < 程序地址空间的页数
,上述判断由硬件自动完成,若不合法,硬件产生越界中断,由操作系统的越界中断处理程序进行处理。在页表中增加用于存取控制和存储保护的信息,当要访问某页时系统要根据该页的存取控制和存储保护信息检查访问是否合法。(主要用于越权保护)
快表
分页管理中,页地址变换过程中有一个严重的问题,就是每一次对内存的访问都要访问页表,页表是放在内存中的,也就是说每一次访问内存的指令至少要访问两次内存,运行速度要下降一半。
解决这个问题的一种方法是把页表放在一组快速存储器中(Cache),从而加快访问内存的速度。这种快速存储器组成的页表称为快表,把存放在内存中的页表称为慢表。快表又叫联想存储器(Associative Memory)或 TLB(Translation Lookaside Buffers)。
此时的映射机制为:
当调度合理时,可以达到97%的效率。也就是说访问页表的速度大致相当于访问快表的速度,考虑到快表的速度是内存速度的数倍或数十倍,那么相对于内存速度,访问页表的时间可以忽略不计。也就是说具有快表的页地址变换不会造成进程运行速度的下降。
两级页表和多级页表
反置页表
所有进程的页表占用大量的存储空间;而反置页表是为系统的每个页面设置一个表项,存放进程号,页号。整个系统只需要维护一张反置页表。使用反置页表可减少页表所占用的内存空间。
例题
题1:在采用页式存储管理的 16 位系统中,某作业 J 的逻辑地址空间为 4 页(每页 2048 字节),且已知该作业的页面映像(即页表)如下:
页号 | 块号 |
---|---|
0 | 2 |
1 | 4 |
2 | 6 |
3 | 8 |
试借助地址变换图求出有效逻辑地址 4865 所对应的物理地址。
可以由 4865 = 2 * 2048 + 769,即 2 为页号,769 为偏移量;再通过页表,得到页号 2 对应为块号 7 ,所以物理地址为 7 * 2048 + 769 = 15105,对应二进制为:00111,01100000001。
题2:在分页存储管理系统中,有一作业大小为 4 页,页长为 2 K,页表如下:
页号 | 块号 |
---|---|
0 | 5 |
1 | 3 |
2 | 7 |
3 | 6 |
试借助地址变换图(即要求画出地址变换图)求出逻辑地址 4635 所对应的物理地址。
4.5 分段存储管理方式
用户程序
按程序自身的逻辑关系划分为若干个程序段,每个程序段都有一个段名,且有一个段号。段号从 0 开始,每一段段内也从0开始编址,段内地址是连续的。
内存空间
内存空间被动态的划分为若干个长度不相同的区域,称为物理段;每个物理段由起始地址和长度确定。
内存分配
以段为单位分配内存,每一个段在内存中占据连续空间;各段之间可以不连续存放。
段表
和分页存储管理类似,分段存储管理方式也有段表:
4.6 段页式存储管理方式
用户程序
按段式划分(对用户来讲,按段的逻辑关系进行划分;对系统讲,按页划分每一段)
逻辑地址
内存划分
按页式存储管理方案
内存分配
以页为单位进行分配
地址映射
段表:记录了每一段的页表始址和页表长度;
页表:记录了逻辑页号与内存块号的对应关系(每段一个页表,一个程序可能有多个页表);
内存分配管理:同页式管理。