第一章 操作系统引论
1.1 操作系统的目标和作用
1.1.1 操作系统的目标
- 方便性:系统可以使用编译命令将用户采用高级语言书写的程序翻译为机器代码
- 有效性:提高资源利用率和系统吞吐量
- 可扩充性:增添模块
- 开放性:彼此兼容
1.1.2 操作系统的作用
- OS作为用户与计算机硬件间的接口
- OS作为计算机系统资源的管理者
- OS实现了对计算机资源的抽象
即:用户通过IO管理OS,OS可以进行对计算机的资源管理和抽象
1.1.3 操作系统发展的主要动力
- 不断提高计算机资源利用率
- 方便用户
- 器件的不断更新迭代
- 计算机体系结构的不断发展
- 不断提出新的应用需求
1.2 操作系统的发展过程
1.2.1 未配置操作系统的计算机系统
- 人工操作方式
- 脱机输入输出方式
1.2.2 单道批处理系统
把作业以脱机方式输入到磁带上,并在系统中配上监督程序,在它的控制下,使这批作业能够被连续处理。
单道批处理系统是在解决人机矛盾和CPU与IO设备速度不匹配的矛盾过程中形成的,旨在提高系统资源的利用率和系统吞吐量
缺点
单道批处理系统最主要的缺点是不能充分地利用系统资源。(要等待I/O操作完成,CPU才能工作)
1.2.3 多道批处理系统
用户所提交的作业先存放在外存上,排成一个队列,称为后备队列,然后由作业调度程序按一定的算法从后被队列中选择若干个作业调入内存,使其共享CPU和系统中的各种资源
优点
- 资源利用率高
- 系统吞吐量大
缺点
- 平均周转时间长
- 无交互能力
需要解决的问题
- 处理机争用
- 内存分配和保护
- IO设备分配
- 文件的组织和管理
- 作业管理
- 用户与系统接口的问题
操作系统的定义
操作系统是一组能够有效地组织和管理计算机硬件和软件资源,合理地对各类作业进行调度,以及方便用户使用的程序的集合。
1.2.4 分时系统
分时系统是指在一台主机上连接了多个配有显示器和键盘终端并由此组成的系统,该系统允许多个用户同时通过自己的终端,以交互方式使用计算机,共享主机中的资源。
要解决的关键问题
1、及时接收: 配置多路卡,它可以实现分时多路复用。
2、及时处理: 人机交互的关键在于,用户键入命令后,能对自己的作业及其运行及时地实施控制,或进行修改。采用方式如下:
(1). 作业直接进入内存:因为作业在磁盘上不能运行,所以作业应直接进入内存。
(2). 采用轮转运行方式:引入时间片的概念,每个作业每次只能运行一个时间片,然后就暂停运行,系统立即调度下一个作业运行。如果在一个不长的时间能使所有的作业都执行一个时间片的时间,便可使每个用户都能及时地与自己的作业进行交互,从而可使用户的请求得到及时响应。
特征
- 多路性
- 独立性
- 及时性
- 交互性
1.2.5 实时系统
实时系统是指系统能够及时响应外部事件的请求,在规定的时间内完成对该事件的处理,并控制所有实时任务协调一致地运行。
类型
- 工业(武器)控制系统
- 信息查询系统
- 多媒体系统
- 嵌入式系统
实时任务的类型:
- 周期性实时任务和非周期性任务
- 硬实时任务和软实时任务
特征
- 多路性
- 独立性
- 及时性
- 交互性
- 可靠性
1.2.6 微机操作系统的发展
单用户单任务操作系统:MS-DOS
单用户多任务操作系统:Windows
多用户多任务操作系统:UNIX OS、Linux OS
1.3 操作系统的基本特性
1.3.1 并发
并发性
操作系统正是有了这一特征,才使得OS能有效地提高系统中的资源利用率,增加系统的吞吐量。
并行与并发:并行性是指两个及以上的时间在同一时刻发生,并发性是指两个及以上的时间在同一时间间隔内发生。
引入进程:进程是指在系统中能独立运行并作为资源分配的基本单位,进程 = 1组机器指令 + 数据 + 堆栈,是一个能独立运行的活动实体。多个进程之间可以并发执行和交换信息。事实上,进程和并发是现代操作系统中最重要的基本概念,也是操作系统运行的基础。
共享性
- 互斥共享方式:系统中某些资源在规定的一段时间内只允许一个进程访问该资源。因此,系统建立了互斥访问机制。
- 同时访问方式:系统中某些资源允许一段时间内多个进程“同时”对它们进行访问。“同时”是宏观意义上的,而在微观上这些进程对该资源的访问是交替进行的。
并发性和共享性是多用户OS的两个最基本的特征,它们也是互为存在的条件。没并发就没共享,没共享就没并发。
虚拟性
在OS中,把通过某种技术将一个物理实体变为若干个逻辑上的对应物的功能称为“虚拟”。前者是实的,即实际存在的,而后者是虚的,是用户感觉上的东西。
虚拟技术:
时分复用技术:该技术能提高资源利用率的根本原因在于,它利用某设备为一个用户服务的空闲时间,又转去为其他用户服务,使设备得到最充分的利用。
(1). 虚拟处理机技术
(2). 虚拟设备技术空分复用技术:如果说,多道程序技术(时分复用技术)是通过处理机的空闲时间运行其它程序,提高了处理机的利用率,那么,空分复用技术则是利用存储器的空闲空间分区域存放和运行其它的多道程序,以此来提高内存的利用率。
异步性
进程是以人们不可预知的速度向前推进的,此即进程的异步性。
1.4 操作系统的主要功能
1.4.1 处理机管理功能
- 进程控制
- 进程同步
- 进程通信
- 调度
1.4.2 存储器管理功能
- 内存分配
- 内存保护
- 地址映射
- 内存扩充
1.4.3 设备管理功能
- 缓冲管理
- 设备分配
- 设备处理
1.4.4 文件管理功能
- 文件存储空间的管理
- 目录管理
- 文件的读/写管理和保护
1.4.5 操作系统与用户之间的接口
- 用户接口
- 程序接口
1.4.6 现代操作系统新功能
- 系统安全
- 网络的功能和服务
- 支持多媒体
第二章 进程的描述与控制
2.1 前驱图和程序执行
2.1.1 前趋图
为了能更好的描述程序的顺序和并发,我们用一个有向无循环图来表示,此图记为DAG,用于描述进程之间执行的先后顺序
2.1.2 程序顺序执行
-
程序的顺序执行
每一个程序段完成特定的功能,在执行时需要按照某种先后次序顺序执行
程序顺序执行的特征
2.1 顺序性:处理机严格按程序规定的顺序执行,即每一操作必须在下一操作开始前结束
2.2 封闭性:程序在封闭环境下运行,即运行时程序独占全机资源
2.3 可再现性:指只要程序执行时环境和初始条件相同,当程序重复执行时,不论从头到尾不停顿还是走走停停,结果都相同
2.1.3 程序并发执行
程序顺序执行时,虽然可以给程序员带来方便,但系统资源利用率很低,为此,引入多道程序技术,使程序或程序间能并发执行。然而并非所有程序都能并发执行,事实上只有不存在前趋关系的程序之间才有可能并发执行,否则无法并发执行
程序并发执行的特征
2.1 间断性:由于共享系统资源,为完成同一任务而相互合作,使得并发执行的程序之间形成了相互制约的关系,导致“执行——暂停——执行”的活动规律
2.2 失去封闭性:当处理机已被分配给某个进程运行时,其他程序必须等待,显然程序已经失去了封闭性
2.3 不可再现性:程序经过多次执行后,即使执行的初始环境相同,但是得到的结果不同
2.2 进程的描述
2.2.1 进程的定义和特征
进程的定义:进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位
进程的特征
2.1 动态性:有生命周期,是实体的执行过程
2.2 并发性:多个进程实体存在于内存中,并能在一段时间内同时运行
2.3 独立性:进程实体是一个能独立运行,独立获得资源和独立接受调度的基本单位。凡未建立PCB的程序都不能作为一个独立的单位运行
2.4 异步性:各自独立,不可预知的速度向前推进。为了使进程在并发时仍可使结果再现,配备了同步机制
2.2.2 进程的基本状态及转换
三种基本状态的转换:
就绪状态:进程已处于准备好运行的状态,分配到除CPU以外的所有必要资源后,只要获得CPU即可执行
执行状态:进程已经获得CPU,程序正在执行的状态
阻塞状态:指正在执行的进程由于发生某事件暂时无法继续执行时的状态,即阻塞
引入创建和终止状态:
创建状态:申请一个空白PCB,并向PCB中填写用于控制和管理进程的信息,然后为该进程分配运行时所必须的资源,最后把该进程转入就绪状态并插入就绪队列中
终止状态:首先等待操作系统进行善后处理,最后将PCB清零,并将PCB空间返回系统。当一个进程达到自然结束点,或出现了无法克服的错误,或被操作系统终结,它将进入终止状态,清零PCB并将空白PCB返回给系统
引入挂起操作:
挂起操作:为了系统和用户观察分析进程的需要,引入了挂起操作,线程被挂起时意味着此时进程处于静止状态。如果进程正在执行,它将暂停执行。如果原本处于就绪状态,则进程此时不接受调度
挂起操作引入的原因:
- 中断用户的需要
- 父进程的请求
- 负荷调节的需要
- 操作系统的需要
2.2.4 进程管理中的数据结构
- 操作系统中用于管理控制的数据结构
计算机系统中,每个资源和每个进程都设置了一个数据结构,用于表征其实体,称之为资源信息表或进程信息表,其中包含了资源或进程的标识,描述,状态等信息以及一批指针,通过指针将同类资源或进程的信息表,或者统一进程所占用的资源信息表分类连接成不同的队列,便于操作系统进行查找
OS管理的数据结构一般分为:内存表,设备表,文件表,用于进程管理的进程表
进程控制块PCB的作用
2.1 作为独立运行基本单位的标志
2.2 能实现间断性运行方式:有了PCB之后,系统就可将CPU现场信息保存在被中断进程的PCB中,供该进程再次被调度执行时恢复CPU现场时使用。
2.3 提供进程管理所需要的信息
2.4 提供进程调度所需要的信息
2.5 实现与其它进程的同步与通信进程控制块中的信息
3.1 进程标识符:唯一地标识一个进程,通常有两种标识符
(1). 外部标识符:方便用户对进程进行访问
(2). 内部标识符:方便系统对进程地使用,赋予每一个进程一个唯一的数字标识
3.2 处理及状态:也称为处理机的上下文,主要是处理机的各种内存中的内容组成的,包括通用寄存器,指令计数器,程序状态字PSW,用户栈指针
3.3 进程调度信息:信息包括进程状态,进程优先级,进程调度所需的其他信息,事件阻塞原因
3.4 进程控制信息:信息包括程序和数据的地址,进程同步和通信机制,资源清单,链接指针-
进程控制块的组织方式
为了有效管理组织PCB,主要方式有以下三种
4.1 线性方式:将所有PCB放在一张表中,每次查找扫描整张表
4.2 链接方式
4.3 索引方式
2.3 进程控制
2.3.1 操作系统内核
绝大多数OS内核都包含了以下两大方面功能
支撑功能
提供给OS其他众多模块所需要的一些基本功能,以便支撑这些模块工作,最基本的三种支撑功能为:
- 中断处理:最基本的功能,是整个OS赖以活动的基础
- 时钟管理:内核的基本功能,进程时长控制
- 原语操作:若干条指令组成,完成一定功能的一个过程,是原子操作,执行时不可被中断
资源管理功能
- 进程管理:进程调度与分派,放在内核中,提高性能
- 存储器管理:存储器管理软件的运行频率较高,放在内核中,保证有较高的运行速度
- 设备管理:与硬件紧密相关,放在内核中
2.3.2 进程的创建
1. 进程的层次结构
OS中允许一个进程创建另一个进程吗,通常把创建进程的进程叫做父进程,被创建的进程称为子进程,如UNIX中,进程与其子孙进程共同组成一个家族
子进程可以继承父进程的所有资源,如父进程打开的文件,所分配到的缓冲区。子进程被撤销时,资源归还给父进程。此外撤销父进程时,也应撤销其所有子进程
值得注意的是Windows不存在任何进程层次结构的概念,所有进程地位相同。如果一个进程创建另外的进程时创建进程获得了一个句柄,作用相当于一个令牌,可以用来控制被创建的进程,句柄是可以传递的,因此进程不再是层次关系,而是获得句柄与否,控制与被控制的关系
2. 进程图
3. 引起创建进程的事件
为使程序之间能并发运行,应先为他们创建进程,导致一个进程去创建另一个进程的典型事件有4种
- 用户登录
- 作业调度
- 提供服务
- 应用请求
4. 进程的创建流程
申请空白PCB:为新进程申请获得唯一的数字标识,并从PCB集合种索取一个空白PCB
为新进程分配其所需的资源:包括各种物理逻辑资源,如内存,文件,IO设备等。这些资源从OS本身或仅从父进程获得,新进程对这些资源的需求详情也要提前告知OS或其父进程
初始化进程控制块PCB:
初始化标识信息,将系统分配的标识符和父进程标识符填入新PCB中
初始化处理机状态信息,使程序计数器指向程序入口地址,使栈帧指向栈顶
初始化处理机控制信息,将进程的状态设置为就绪状态或静止就绪状态,对于优先级通常是将他们设置为最低优先级如果进程就绪队列能够接纳新进程,便将新进程插入就绪队列
2.3.3 进程的终止
1. 引起进程终止的事件
- 正常结束:任务完成,准备退出
- 异常结束:越界错,保护错,非法指令,特权指令错,运行超时,等待超时,算数运算错,IO故障等
- 外界干预:程序外界请求而终止运行,如操作系统干预,父进程请求,父进程终止等
2. 进程的终止过程
- 根据被终止进程的标识符
- 若被终止进程正处于执行状态
- 若该进程还有子孙进程
- 将被终止进程所拥有的全部资源或者归还给父进程
- 将被终止进程从所在队列中移出
2.3.4 进程的阻塞和唤醒
1. 引起进程阻塞和唤醒的事件
- 向系统请求共享资源失败
- 等待某种操作的完成
- 新数据尚未到达
- 等待新任务的到达
2. 进程阻塞过程
正在执行的进程,如果发生了上述某事件,进程便通过调用阻塞原语block将自己阻塞,可见阻塞是一种主动行为。进入block过程后,由于该进程还处于执行状态,所以应先立即停止执行,把进程控制块中的先行状态由执行改为阻塞,并将PCB插入到阻塞队列
3. 进程唤醒过程
当被阻塞的进程所期待的事件发生时,有关进程调用唤醒原语wakeup,将等待中的进程唤醒。wakeup的执行过程是首先把被阻塞的进程从等待该事件的阻塞队列中移出,将其PCB中的现行状态由阻塞改为就绪,然后将PCB插入到就绪队列中
注意的是,block和wakeup是一对作用相反的原语,使用时必须成对使用,否则线程将因阻塞而无法被唤醒,再无机会运行
2.3.5 进程的挂起与激活
1. 进程的挂起
当系统中出现进程挂起事件时,OS调用挂起原语suspend将指定进程或处于阻塞状态的进程挂起。suspend的执行过程是首先检查被挂起进程的状态,若处于活动就绪状态,便将其改为静止就绪。对于活动阻塞状态的进程,则改为静止阻塞。为了方便父进程考察该进程的运行状态,把该进程的PCB复制到指定内存区域。最后若被挂起的进程正在执行,则转向调度程序重新调度
2. 进程的激活过程
当系统中发生激活进程的事件时,OS调用激活原语active,将指定进程激活。先将进程从外存调入内存,检查进程的现行状态。若是静止就绪,则改为活动就绪。若为静止阻塞,则改为活动阻塞。加入采用抢占式调度策略,每当有静止就绪进程被激活而插入就绪队列时,便应检查是否要进行重新调度,即由调度程序将被激活的进程与当前进程两者的优先级进行比较,如果被激活的进程优先级低,则不必重新调度,否则,立即剥夺当前进程的运行,把处理机分配给刚刚被激活的进程
2.4 进程同步
OS中引入进程后,一方面使系统中多道程序并发执行,有效改善资源利用率和系统吞吐量,但也使得系统变得复杂,不妥善处理,会使程序结果存在不确定性
2.4.1 进程同步的基本概念
进程同步机制的主要任务是对多个相关程序在执行次序上进行协调,使并发执行的进程间能很好的互相合作,共享资源,从而使程序有可再现性
1. 两种形式的制约关系
多道程序环境下,对于同处于一个系统中的多个进程,由于他们共享系统中的资源,或为完成某一任务而合作,他们之间可能存在着以下两种形式的制约关系
- 间接相互制约:由于程序并发执行时共享系统资源,使这些并发执行的程序之间形成相互制约的关系,对于一些临界资源必须保证多个进程对其只能互斥的进行访问,由此形成了资源共享的所谓间接相互制约的关系
- 直接相互制约:为了完成某任务而建立两个或多个进程,这些进程将为完成同一项任务而相互合作。进程间的直接制约关系就是源于它们之间的相互合作
另外,在多道程序环境下,由于存在上述两类相互制约关系,进程在运行过程中能否获得处理及运行与以怎样的速度运行,并不能由进程自身控制,此即异步性。由此产生对共享变量或数据结构等资源不正确的访问次序,从而造成结果不一致。为杜绝这种差错,则必须对进程的执行次序进行协调,保证按顺序执行。
2. 临界资源和临界区
不论是硬件临界资源还是软件临界资源,多个线程必须互斥地进行访问,每个进程中访问临界资源的代码就是临界区。为此,每个线程在进入临界区前应先对欲访问的临界资源进行检查,看它是否被访问,这段代码叫进入区。相应的,在临界区后也要加上一段代码,称为退出区。其余部分叫做剩余区,代码描述如下:
while(TRUE){
进入区
临界区
退出区
剩余区
}
4. 同步机制应遵循的规则
- 空闲让进:无进程处于临界区时,资源空闲,允许进入
- 忙则等待:已有线程进入临界区,临界资源正在被访问, 其他试图进入临界区的进程必须等待,保证互斥访问
- 有限等待:对要求访问临界资源的进程,应保证在有限时间内能进入自己的临界区,防止“死等状态”
- 让权等待:当进程不能进入自己的临界区时,应立即释放处理机,以免进程陷入“忙等”状态
2.4.2 硬件同步机制
关中断
是实现互斥的最简单方法之一。在进入锁测试之前关闭中断,直到完成锁测试并上锁之后才能打开中断。
利用Test-and-Set指令实现互斥
硬件指令,测试并建立,以实现互斥
Swap指令实现进程互斥
对换指令,用于交换两个字的内容
2.4.3 信号量机制
信号量S是一个整数,S大于等于零是代表可供并发进程使用的资源实体数,当S小于零时则表示正在等待使用临界区的进程数,Dijkstra同时提出了对信号量操作的PV原语
P原语操作的动作是:
- S减1;
- 若S减1后仍大于或等于零,则进程继续执行;
- 若S减1后小于零,则该进程被阻塞后进入与该信号相对应的队列中,然后转进程调度
V原语操作的动作是:
- S加1;
- 若相加结果大于零,则进程继续执行;
- 若相加结果小于或等于零,则从该信号的等待队列中唤醒一等待进程,然后再返回原进程继续执行或转进程调度
PV操作对于每一个进程来说,都只能进行一次,而且必须成对使用。在PV原语执行期间不允许有中断的发生
2.5 经典的进程同步问题
2.5.1 生产者消费者问题
输入时,输入进程是生产者,计算机进程是消费者。输出时,计算机进程是生产者,打印进程是消费者
2.5.2 哲学家进餐问题
五个哲学家公用一张圆桌,分别坐在周围五张椅子上。在圆桌上由五个碗和五只筷子,他们的生活方式是交替的进行思考和进餐,平时一个哲学家进行思考,饥饿时拿取其左右靠他最近的筷子,只有在他拿到两只筷子时才能进餐,进餐后则继续思考
2.5.3 读者写者问题
一个数据文件或记录被多个进程共享,我们把只要求度该文件的进程称为读者,其他进程称为写者。允许多个进程同时读一个共享对象,因为读操作不会使数据文件混乱。但不允许一个写者进程和其他读者进程或写者进程同时访问共享对象,因为这种访问会引起混乱。所以这个问题是指保证一个写者进程必须与其他进程互斥地访问共享对象的同步问题,常被用来测试新同步原语
第三章 处理机调度与死锁
3.1 处理机调度的层次和调度算法的目标
调度实质上是一种资源的分配,处理机调度是对处理机资源的分配,调度算法是指根据处理机分配策略所规定的处理机分配算法。
3.1.1 处理机调度的层次
1. 高级调度
高级调度又称长程调度,作业调度。调度对象是作业。根据算法将外存上处于后备队列中的哪几个作业调入内存,为他们分配资源,创建进程。主要用于多批道处理系统,分时系统和实时系统不设置高级调度
2. 低级调度
低级调度又称短程调度或进程调度。调度对象是进程。根据算法决定就绪队列中的哪个进程获得处理机,由分派程序将处理机分配给选中的进程,是一种最基本的调度,在多批道处理,分时,实时三种OS中都必须设置
3. 中级调度
中级调度又称内存调度,目的是提高内存利用率和系统吞吐量,运行频率介于上述两种之间
上述三种调度中,进程调度运行频率最高,仅10~100ms便进行一次,因此称为短程调度。为避免占用太多CPU时间,不宜将进程调度算法设计复杂。
作业调度往往发生在一批作业已经运行完毕退出系统,需要重新调入一批作业进入内存时,作业调度的周期较长,大约几分钟一次,因此称为长程调度。由于其运行频率较低,故允许作业调度算法花费较多时间
中级调度运行频率基本处于两种调度之间,因此称为中级调度
3.1.2 处理机调度算法的目标
1. 处理机调度算法的共同目标
1.1 资源利用率:CPU利用率 = CPU有效工作时间 / (CPU有效工作时间 + CPU空闲等待时间)
1.2 公平性:应使诸进程获得合理的CPU时间,不发生饥饿现象
1.3 平衡性: 使CPU和各种外设都能经常处于忙碌状态
1.4 策略强制执行: 如安全策略,只要需要,必须予以准确执行
2. 批处理系统的目标
2.1 平均周转时间短:平均周转时间可描述为 T = (1 / n) * (T1 + T2 + T3 + ... + Ti)。平均带权周转时间可描述为 W = T / Ts,Ts为系统为其提供服务的时间
2.2 系统吞吐量高
2.3 处理机利用率高
3. 分时系统的目标
- 响应时间快
- 均衡性
4. 实时系统的目标
- 截至时间的保证
- 可预测性
3.2 作业与作业调度
3.2.1 批处理系统中的作业
1. 作业和作业步
- 作业:作业是一个比程序更广泛的概念,不仅包含了通常的程序和数据,还应配有一份作业说明书,系统根据说明书对程序运行进行控制,在批处理系统中,是以作业为基本单位从外存调入内存的
- 作业步:作业运行期间,每个作业都必须经过若干个相对独立又相互关联的顺序加工步骤才能得到结果,每一个加工步骤叫做作业步
2. 作业控制块
每当一个作业进入系统,作业注册程序为该作业创建一个作业控制块JCB,根据作业类型,放入对应的作业后备队列等待调度。作业结束时,系统负责回收并撤销
3. 作业运行的三个阶段和三种状态
- 收容阶段——后备状态
- 运行阶段——运行状态
- 完成阶段——完成状态
3.2.2 作业调度的主要任务
- 接纳多少作业
- 接纳哪些作业
3.2.3 先来先服务(FCFS) & 短作业优先(SJF)
FCFS:最简单的调度算法,作业调度和进程调度都可用。当采用该算法时,系统按照作业到达的先后次序来进行调度,或者说它是优先考虑在系统中等待时间最长的作业,而不管该作业所需执行时间的长短。
SJF:由于短作业实际上占很大比例,为了能使其比长作业优先进行,便以作业长短计算优先级,作业越短,其调度优先级越高。分别可用于作业调度和进程调度
SJF算法优缺点:
- 必须预知作业的运行时间
- 对长作业非常不利,长作业的周转时间会明显地增长
- 采用FCFS算法时,人—机无法实现交互
- 该调度算法完全未考虑作业的紧迫程度,故不能保证紧迫性作业能得到及时处理
3.2.4优先级调度算法(PSA) & 高响应比优先调度算法(HRRN)
PSA:基于作业的紧迫程度,由外部赋予优先级,系统从后备队列中选择若干个优先级最高的作业放入内存
HRRN:既照顾了短作业,又不致使长作业的等待时间过长,从而改善了处理机调度的性能。
由上述公式可以看出:
- 如果作业的等待时间相同,则要求服务的时间愈短,其优先权越高,类似于SJF算法,有利于短作业
- 当要求服务的时间相同时,等待时间越长的优先权越高,类似于FCFS算法
- 对于长作业的优先级,可以随等待时间的增加而增高,当其等待时间足够长时,也可以获得处理机,因此该算法实现了较好的折中。但利用该算法的每次进行调度之前,都需要先做响应比的计算,会增加系统开销
3.3 进程调度
进程调度是对OS系统性能影响最大的调度
3.3.1 进程调度的任务,机制和方式
1. 进程调度的任务
- 保存处理机的现场信息
- 按某种算法选取进程
- 把处理器分配给进程
2. 进程调度机制
进程调度机制中,有下面三个基本部分
排队器:提高进程调度效率,如下策略排成一个或多个队列,以便调度程序能尽快找到它,以后每当有一个进程转变为就绪状态时,排队器便将它插入到相应的就绪队列
分派器:根据进程调度程序所选定的进程,将其从就绪队列中取出,然后进行从分派器道新选出的进程间的上下文切换,将处理机分配给新选出的进程
-
上下文切换器:对处理机进行切换时,会发生两对上下文的切换操作
3.1 第一对上下文切换时,OS保存当前进程的上下文,把当前进程的处理机寄存器内容保存到该进程的进程控制块的相应单元,再装入分派程序的上下文,以便分派程序运行
3.2 第二对上下文切换时是移除分派程序的上下文,而把新选进程的CPU现场信息装入到处理机的各个相应寄存器中,以便新选进程运行
3. 进程调度方式
- 非抢占方式 :采用这种调度方式时,一旦把处理机分配给某进程后,就一直让它运行下去,绝不会因为时钟中断或者任何其它原因去抢占当前正在运行进程的处理机,直至该进程完成,或者发生某事件而被阻塞时,才把处理机分配给其他进程。
采用该方式引起调度的因素有:
- 正在执行的进程运行完毕或者因发生某事件而使其无法再继续运行
- 正在执行中的进程因提出I/O请求而暂停运行
- 在进程通信或同步过程中,执行了某种原语操作,如Block原语。
这种调度方式的优点是实现简单,系统开销小,适用于大多数的批处理系统。但不能用于分时系统和大多数实时系统。
- 抢占方式:这种调度方式允许调度程序根据某种原则,去暂停某个正在执行的进程,将已分配给该进程的处理机重新分配给另一进程。现代OS广泛采用抢占方式。对于批处理系统,该方式可以防止一个长进程长时间地占用处理机,以确保处理机能为所有进程提供更为公平的服务。在分时系统中,只有使用抢占方式才有可能实现人—机交互。在实时系统中,抢占方式能满足实时任务的需求。但抢占方式比较复杂,所需付出的系统开销也比较大
“抢占”不是一种任意性行为,必须遵循一定的原则
- 优先权原则:允许优先级高的新线程抢占当前进程的处理机
- 短进程优先原则:新到的短进程可以抢占当前长进程的处理机
- 时间片原则:各进程按时间片轮转运行,时间片用完后则停止该进程执行
3.3.2 轮转调度算法
该算法假设所有作业优先级都相同(但实际并非如此),采用非常公平的处理机分配方式,让就绪队列上的每个进程每次仅运行一个时间片,如果就绪队列上有n个进程,则每个进程每次大约都可获得1/n的处理机时间
基本原理
根据FCFS策略,将所有的就绪进程排成一个就绪队列,设置一定时间间隔产生一次中断,激活系统中的进程调度程序,完成一次调度,将CPU分配给队首进程。该进程运行完毕时再将CPU分配给此时的队首进程,所有进程在一个确定时间段内都可获得一次CPU执行
进程切换时机
- 若时间片尚未用完,正在运行的进程就已经完成,立即激活调度程序,将它从就绪队列中删除,再调度就绪队列中队首的进程运行,并启动一个新的时间片
- 在一个时间片用完时,计时器中断处理程序被激活。如果进程尚未运行完毕,调度程序将把它送往就绪队列的末尾
时间片大小的确定
在RR算法中,时间片大小的确定对系统性能有很大的影响,如果选择很小的时间片,将有利于短作业,因为它能够在该时间片内完成。但时间片小,意味着会频繁地执行进程调度和进程上下文的切换,这无疑会增加系统的开销。反之,如果时间片选择得太长,且为使每个进程都能在一个时间片内完成,RR算法便退化为FCFS算法,无法满足短作业和交互式用户的需求。一个较为可取的时间片大小使略大于一次典型的交互所需要的时间,使大多数交互式进程能在一个时间片内完成,从而获得很小的响应时间
3.3.3 优先级调度算法
将处理机分配给就绪队列中优先级最高的进程,该算法进一步分为以下两种
非抢占式优先级调度算法:一旦处理机分配给就绪队列中的最高优先级进程后,该进程一直执行下去直到结束,系统才将处理机分配给下一优先级最高的进程运行
抢占式优先级调度算法:把处理机分配给优先级最高的进程,使之执行,但在运行期出现了另一个优先级更高的进程,就分配给这个优先级更高的进程运行
优先级的类型
静态优先级:创建进程时确定,整个运行期保持不变。确定优先级的依据有进程类型,用户要求,和进程对资源的需求三方面
动态优先级:创建进程时,赋予一个优先级,其值随着进程推进或等待的时间增加而改变,获得更好的调度性能
3.3.4 多队列调度算法
弥补不同用户对进程调度不同要求,该算法将系统中的进程就绪队列从一个拆分为若干个,将不同类型或性质的进程固定分配在不同的就绪队列中,不同的就绪队列采用不同的调度算法,一个就绪队列中的进程可以设置在不同的优先级,不同的就绪队列本身也可以设置不同的优先级。因此,系统可以针对不同用户进程的需求,很容易提供多种调度策略。
3.3.5 多级反馈队列
前面的一些算法都有一定的局限性,此算法不必事先知道各进程的运行时间,还可以较好地满足各类型进程的需要,是目前公认的比较好的算法
调度机制
- 设置多个就绪队列:第一个队列优先级最高,第二个次之,其余队列的优先级逐个降低。优先级越高的队列中,时间片越小。例如第二个队列的时间片要比第一个的时间片长一倍,第i+1个队列要比第i个的时间片长一倍
- 每个队列都采用FCFS算法,当轮到某个队列的某个进程执行时,如它能在该时间片内完成,便可撤离系统,否则调度程序将其转入下一个队列等待调度,以此类推,当进程最后被降到第n个队列后,在第n个队列中便采取按RR方式运行
-
按队列优先级调度。调度程序首先调度最高优先级队列中的诸进程运行, 仅当第1~(i-1)所有队列均空时,才会调度第i队列中的进程运行。如果处理机正在第i队列中为某进程服务时又有新进程进入任一优先级较高的队列,此时须立即把正在运行的进程放回到第i队列的末尾,而把处理机分配给新到的高优先级进程
调度性能
- 终端型用户。由于终端型用户提交的作业多属于交互型作业,通常较小,系统只要能使这些作业在第一队列规定的时间片内完成,便可使终端型用户感到满意
- 短批处理作业用户。对于这类作业,如果可在第一队列中执行完成,便获得与终端型作业一样的响应时间。对于稍长的短作业,也只需在第二和第三队列各执行一时间片完成,其周转时间仍然较短
- 长批处理作业用户。对于长作业,它将依次在第1,2,…,n个队列中运行,然后再按轮转方式运行,用户不必担心其作业长期得不到处理
3.4 实时调度
3.4.1 实现实时调度的基本条件
提供必要的信息
- 就绪时间
- 开始截止时间和完成截至时间
- 处理时间
- 资源要求
- 优先级
系统处理能力强
提高系统处理能力途径有二:一是采用单处理机系统,增强处理能力。二是采用多处理机系统
采用抢占式调度机制
满足HRT任务对截止时间的要求
4. 具有快速切换机制
- 对中断的快速响应能力
- 快速的任务分派能力
3.4.2 实时调度算法的分类
- 非抢占式调度算法
- 抢占式调度算法
3.4.3 最早截止时间优先算法(EDF)
根据任务的最早截止时间为优先级,结束越早,优先级越高
3.5 死锁概述
资源问题
可重用性资源:可供用户重复使用多次的资源,每个可重用性资源中的单元只能分配给一个进程使用,不允许多个进程共享
可消耗性资源(临时性资源):它是在进程运行期间,由进程动态地创建和消耗的,可消耗性资源通常是由生产者进程创建,由消费者进程消耗
可抢占性资源:某进程在获得这类资源后,该资源又可以再被其它进程或系统抢占。CPU和主存均属于可抢占性资源。这类资源不会引起死锁
不可抢占性资源:一旦系统把某资源分配给该进程后,就不能将它强行收回,只能在进程用完后自行释放
3.5.2 计算机系统中的死锁
通常是源于多个进程对资源的争夺
- 对不可抢占资源进行争夺时会引起死锁
- 对可消耗性资源进行争夺时会引起死锁
- 进程推进顺序不当会引起死锁。
3.5.3 死锁定义,必要条件和处理方法
死锁的定义
如果一组进程中的每一个进程都在等待仅由改组进程中的其它进程才能引发的事件,那么该组进程是死锁的。
产生死锁的必要条件
只要下面四个条件任意一个不成立死锁都不会发生
- 互斥条件
- 请求和保持条件
- 不可抢占条件
- 循环等待条件
处理死锁的方法
- 预防死锁
- 避免死锁
- 检测死锁
- 解除死锁
从上到下对死锁的防范程度逐渐减弱,但对应的是资源利用率的提高,以及进程因资源因素而阻塞的频度下降(即并发程度提高)
3.6 预防死锁
预防死锁是破坏一个或几个产生死锁的必要条件来避免死锁发生,由于互斥条件是非共享设备所必须的,不仅不能改变,还要加以保证,因此,主要是破坏产生死锁的后三个条件。
3.6.1 破坏“请求和保持”条件
第一种协议
所有进程在开始运行之前,必须一次性地申请其在整个运行过程中所需的全部资源。只要有一种资源不能满足进程的要求,即使其它所需的各资源都空闲也不分配给该进程,而让该进程等待
优点:简单,易行,安全
缺点:资源被严重浪费,使进程经常会发生饥饿现象
第二种协议
它允许一个进程只获得运行初期所需的资源后,便开始运行。进程运行过程中再逐步释放已分配给自己的、且已用毕的全部资源,然后再请求新的所需资源。
优点:更快完成任务,提高利用率,减少饥饿几率
3.6.2 破坏“不可抢占”条件
当一个已经保持了某些不可被抢占资源的进程,提出新的资源请求而不能得到满足时,它必须释放已经保持的所有资源,待以后需要时再重新申请。
缺点:延长了进程的周转时间,增加了系统开销,降低了系统吞吐量
3.6.3 破坏“循环等待”条件
一个能保证“循环等待”条件不成立的方法是,对系统所有资源类型进行线性排序,并赋予不同的序号,之后规定每个进程必须按序号递增的顺序请求资源。
3.7 避免死锁:
当系统进入不安全状态之后,就有可能进入死锁状态。相反,只要系统处于安全状态,系统便不会进入死锁状态。
3.7.1 系统安全状态
安全状态
安全状态指系统能按某种进程推进顺序为每个进程分配所需的资源,直至满足每个进程对资源的最大需求,使每个进程可以顺利完成
3.7.2 银行家算法避免死锁
此处书上内容过多,难以总结,图片摘自知乎 @Fdaxiong大熊
3.8 死锁的检测与解除
如果在系统中,既不采取死锁预防措施,也未配有死锁避免算法,系统很可能会发生死锁,此时系统应该提供两个算法
- 死锁检测算法:该方法用于检测系统状态,以确定系统中是否发生了死锁
- 死锁解除算法:当认定系统中发生了死锁,利用该算法可将系统从死锁状态中解脱出来
3.8.1 死锁的检测
为了能对系统中是否发生了死锁进行检测,系统中必须保存有关资源的请求和分配信息,提供一种算法,利用这些信息来检测系统是否已进入死锁状态
资源分配图
该图是由一组结点N和一组边E所组成的一个对偶G = (N,E),它具有下述形式的定义和限制
- 把N分为两个互斥的子集,即一组进程结点P和一组资源节点R。N = P U R
-
凡属于E中的一个边e,都连接着P中的一个节点和R中的一个节点
我们用圆圈代表一个进程,用方框代表一类资源。由于一种类型的资源可能有多个,我们用方框中的一个点代表一类资源中的一个资源。此时请求边是由进程指向方框中中的Rj,而分配边则应始于方框中的一个点
死锁定理
利用把资源分配图加以简化的方法,来检测当系统处于S状态时是否为死锁状态。简化后若能消去图中所有边,使所有进程的结点都成为孤立结点,则称为可完全简化图,反之则称为不可完全简化图,同样可以证明S为死锁状态的充分条件是:当且仅当S状态的资源分配图是不可完全简化的,该充分条件称为死锁定理
死锁检测中的数据结构
- 可利用资源向量Available
- 不占用资源的进程记入L表中
- 从进程集合中找到一个Request小于等于Work的进程,将其资源分配图简化释放资源,增加工作向量Work += Allocation,记入L表中
- 若不能把所有进程都计入L表中,便表明系统状态S的资源分配图是不可完全简化的,因此发生死锁
3.8.2 死锁的解除
如果利用死锁检测算法检测出在系统中发生死锁,应立即解除死锁,常用解除死锁的方式有两种
- 抢占资源:从一个或多个进程中抢占足够数量的资源,分配给死锁进程,以解除死锁状态
- 终止进程:终止系统中的一个或多个死锁进程,直至打破循环环路,使系统从死锁状态中解脱出来
终止进程的方法
- 终止所有死锁进程:这是最简单的方法,但是代价很大,因为有的进程可能已经运行了很久
- 逐个终止进程:按照某种顺序温和的终止进程,直到有足够的资源打破循环等待,把系统从死锁状态中解脱出来。但是该方法所付出的代价可能也很大,因为每终止一个进程都需要用死锁检测算法确定系统死锁是否已经被解除,若未解除还需要再终止另一个进程
付出代价最小的死锁解除算法
找到付出代价最小的终止顺序,但成本高的算法:
1.1 先从死锁进程组中取出一个,形成第一层终止,若有n个死锁进程,则有n个第一层
1.2 再从n个第一层中取一个,形成第二层终止,每个第一层又有n-1个第二层终止
1.3 如此循环,直到解除死锁,将各层的总代价计算,得到最小的终止顺序一种比较有效的算法:
2.1 找到死锁进程组中,终止代价最小的,将其从死锁进程组中删去
2.2 再从新的死锁进程组中,找到终止代价最小的,删去
2.3 如此循环,直到解除死锁
第四章 存储器管理
4.1 存储器的层次结构
4.1.1 多层结构的存储器系统
存储器的多层结构
对于通用计算机而言,存储层次至少应具有三级:最高层为CPU寄存器,中间为主存,最底层是辅存,层次越高,访问速度越快,价格也越高,相应的配置存储容量则越小。CPU寄存器和主存都是操作系统所管辖范围,掉电后信息丢失,辅存属于可移动设备,存储的信息可以被长期保存
可执行存储器
寄存器和主存储器也被称为可执行存储器,操作系统的存储管理负责对可执行存储器的分配,回收,以及提供在存储层次间数据移动的管理机制
4.1.2 主存储器和寄存器
主存储器
主存储器简称内存或主存,是计算机系统中的主要部件,用于保存进程运行时的程序和数据,也称可执行存储器。通常,处理机都是从主存储器中取得指令和数据的,并将其所取得的指令放入指令寄存器中,而将其所读取的数据装入到数据寄存器中,或者反之,将寄存器中的数据存入到主存储器。由于主存储器的访问速度远低于CPU执行指令的速度,为了缓和这一矛盾,在计算机系统中引入了寄存器和高速缓存
寄存器
寄存器具有与处理机相同的速度,故对寄存器的访问速度最快,完全能与CPU协调工作,但价格十分昂贵,因此容量不能做得很大
4.1.3 高速缓存和磁盘缓存
高速缓存
高速缓存用于缓和内存与处理机速度不匹配问题,它是介于寄存器和存储器之间的存储器,主要用于备份主存中较常用的数据,以减少处理机对主存储器的访问次数,这样可大幅度提高程序执行速度。高速缓存容量远大于寄存器,而比内存约小两到三个数量级左右。访问速度快于主存储器,同时由于速度快价格也越贵,在现有计算机体系中设置了两级或多级高速缓存,紧靠内存的一级高速缓存的速度最高,而容量最小,二级高速缓存的容量稍大,速度也稍低
高速缓存涉及到局部性原理:程序执行时将呈现出局部性规律,即在一较短的时间内,程序的执行仅局限于某个部分
磁盘缓存
由于目前磁盘的I/O速度远低于对主存的访问速度,为了缓和两者之间在速度上的不匹配,而设置了磁盘缓存,主要用于暂时存放频繁使用的一部分磁盘数据和信息,以减少访问磁盘的次数
但磁盘缓存与高速缓存不同,它是利用主存中的部分存储空间暂时存放从磁盘中读出或(写入)的信息。主存也可以看作是辅存的高速缓存,因为,辅存中的数据必须复制到主存方能使用,反之,数据也必须先存在主存中,才能输出到辅存
一个文件的数据可能先后出现在不同层次的存储器中
4.2 程序的装入和链接
用户程序要在系统中运行,必须先将他装入内存,然后再将其转变为一个可以执行的程序,通常都要经过以下几个步骤:
- 编译:由编译程序对用户源程序进行编译,形成若干个目标模块。
- 链接:由链接程序将编译后形成的一组目标模块以及它们所需要的库函数链接在一起,形成一个完整的装入模块。
-
装入:由装入程序将装入模块装入内存。
4.2.1 程序的装入
绝对装入方式
当计算机系统很小,且仅能运行单道程序时,完全有可能知道程序将驻留在内存的什么位置,此时可以采用绝对装入方式。用户程序经编译后,将产生绝对地址(物理地址)的目标代码
可重定位装入方式:
在多道程序环境下,编译程序不可能预知经编译后所得到的目标模块应放在内存何处。此时,不可能再用绝对装入方式,而应采用可重定位装入方式,它可以根据内存的具体情况将装入模块装入到内存的适当位置
通常,把在装入时对目标程序中指令和数据地址的修改过程称为重定位。又因为地址变换通常是在进程装入时一次完成的,以后不再改变,故称为静态重定位
动态运行时的装入方式:
动态运行时的装入程序在把装入模块装入内存后,并不立即把装入模块中的逻辑地址转换为物理地址,而是把这种地址转换推迟到程序真正要执行时才进行。因此,装入内存后的所有地址都仍是逻辑地址
4.2.2 程序的链接
源程序经过编译后,可得到一组目标模块。链接程序的功能是将这组目标模块以及它们所需要的库函数装配成一个完整的装入模块。在对目标模块进行链接时,根据进行链接的时间不同,可把链接分成如下三种
静态链接方式
在程序运行之前,先将各目标模块及它们所需的库函数链接成一个完整的装配模块,以后不再拆开
需要解决的问题:
- 对相对地址进行修改
-
变换外部调用符号
装入时动态链接
将用户源程序编译后所得到的一组目标模块,在装入内存时,采用边装入边链接的链接方式。即在装入一个目标模块时若发生一个外部模块调用事件,将引起装入程序去找出相应的外部目标模块,并将它装入内存,还要按照图4-4所示的方式修改目标模块中的相对地址
优点:
- 便于修改和更新
- 便于实现对目标模块的共享
运行时动态链接
在执行过程中,当发现一个被调用模块尚未被装入内存时,立即由OS去找到该模块,并将之装入内存,将其链接到调用者模块上。凡在执行过程中未被用到的目标模块,都不会被调入内存和被链接到装入模块上,这样不仅能加快程序的装入过程,而且可节省大量的内存空间
4.3 连续分配存储管理方式
4.3.1 单一连续分配
在单道程序环境下,当时的存储管理方式是把内存分为系统区和用户区两部分,系统区仅提供给OS使用,它通常是放在内存的低址部分。而在用户区内存中,仅装有一道用户程序,即整个内存的用户空间由该程序独占
4.3.2 固定分区分配
为了能在内存中装入多道程序,且使这些程序之间又不会发生相互干扰,于是将整个用户空间划分为若干个固定大小的区域,在每个分区中只装入一道作业
划分分区的方法
分区大小相等
缺点是缺乏灵活性,即当程序太小时,会造成内存空间的浪费。当程序太大时,一个分区又不足以装入该程序,致使该程序无法运行。尽管如此,对于利用一台计算机同时控制多个相同对象的场合,因为这些对象所需的内存空间大小往往相同,这种划分方式比较方便和实用分区大小不等
为了增加存储器分配的灵活性,应将存储器分区划分为若干个大小不等的分区
内存分配
为了便于内存分配,通常将分区按其大小进行排队,并为之建立一张分区使用表,其中各表项包括每个分区的起始地址、大小及状态(是否已分配)
4.3.3 动态分区分配
也叫可变分区分配,它是根据进程的实际需要,动态地为之分配内存空间。在实现动态分区分配时,将涉及到分区分配中所用的数据结构,分区分配算法和分区的分配与回收操作这样三方面的问题
数据结构
常用数据结构有以下两种形式
空闲分区表:设置一张空闲分区表,用于记录每个空闲分区的情况
空闲分区链:实现对空闲分区的分配和链接,每个分区的起始部分设置一些用于控制分区分配的信息
动态分区分配算法
把一个新作业装入内存,必须按照一定的算法,从上述两种数据结构中选出一分区分配给该作业,由此,产生了顺序式搜索算法和索引式搜索算法
分区分配的操作
分配内存:从数据结构中找到所需大小的分区,划分给请求者
回收内存:进程运行完毕后释放内存,系统根据回收区的首地址,从空闲区链表中找到相应的插入点,此时可能出现四种情况之一
2.1 回收区与插入点的前一个空闲分区F1相邻接,此时应将回收区与插入点的前一分区合并,不必为回收分区分配新表项,而只需修改其前一分区的大小
2.2 回收分区与插入点的后一空闲分区F2相邻接,此时也可将两分区合并,形成新的空闲分区,但用回收区的首地址作为新空闲区的首地址,大小为两者大小之和
2.3 回收区同时与插入点前后两个分区邻接,此时将三个分区合并,使用F1的表项和F1的首地址,取消F2的表项,大小为三者之和
2.4 回收区既不与F1邻接,又不与F2邻接,这时应为回收区单独建立一个新表项,填写回收区的首地址和大小,并根据其首地址插入到空闲链表中的适当位置
4.3.4 基于顺序搜索的动态分区分配算法
这种算法适用于不太大的系统
首次适应算法(FF)
此算法要求空闲分区分链以地址递增的次序链接,分配内存时,从链首开始顺序查找,直到找到一个大小能满足要求的空闲分区为止,再按照作业的大小,从该分区中划出一块内存空间,分配给请求者,剩下的空闲分区仍留在空闲链中。
若从链首开始直到链尾都不能找到一个能满足要求的分区,则表明系统中已经没有足够的内存分配给该进程,内存分配失败,返回
每次查找都是从低地址部分开始的,无疑会增加查找可用空闲分区的开销
循环首次适应算法(NF)
为避免低地址部分出现很多很小的空闲分区,以及减少查找可用空闲分区的开销,此算法每次从上次找到的空闲分区的下一个空闲分区开始查找,直到找到一个能满足要求的空闲分区,并采用循环查找的方式,如果最后一个空闲分区的大小仍不能满足要求,则返回第一个空闲分区。
减少了查找空闲分区的开销,但这样会缺乏大的空闲分区
最佳适应算法(BF)
每次为作业分配内存时,总是把能满足要求又是最小的空闲分区分配给作业,避免大材小用。为了加速寻找,该算法要求将所有的空闲分区按容量从小到大的顺序形成一空闲分区链,这样,第一次找到的分区必然是最佳的。
但是这样会在存储器中留下许多难以利用的碎片
最坏适应算法(WF)
与最佳适应正好相反,扫描整个链表时,总是挑选一个最大的空闲区,从中分割一部分存储空间给作业使用
优点是可以使剩下的空闲分区不至于太小,产生碎片的可能性最小,对中小作业有利。同时效率很高,该算法要求所有空闲分区按从大到小排列,查找时只需要看第一个分区能否满足作业要求即可
4.3.5 基于索引搜索的动态分区分配算法
适用于大、中型系统
快速适应算法(QF)
也称为分类搜索算法,将空闲分区根据容量大小进行分类,对于每一类具有相同容量的所有空闲分区,单独设立一个空闲分区链表
搜索时分两步。第一步根据进程长度,从索引表中去寻找能容纳它的最小空闲区链表。第二步是从链表中取下第一块进行分配即可。
进行空闲分区分配时不会对任何分区产生分割,能保留大分区,满足对大空间的需求,也不会产生内存碎片,查找效率高。但也有缺点在于为了有效合并分区,分区归还时算法复杂,系统开销较大,为进程分配一个分区中或多或少存在浪费,典型的以空间换时间
伙伴系统(BS)
算法规定不论分区已分配或空闲,大小均为2的k次幂,系统运行过程中由于不断划分形成若干个不连续的空闲分区,将这些空闲分区按分区大小进行分类。对于具有相同大小的所有空闲分区单独设立一个空闲分区双向链表,这样不同大小的空闲分区形成了k个空闲分区链表
当分配内存时,会优先从需要分配的内存块链表上查找空闲内存块,当发现对应大小的内存块都已经被使用后,那么会从更大一级的内存块上分配一块内存,并且分成一半给我们使用,剩余的一半释放到对应大小的内存块链表上。比如我们想要分配一个8KB大小的内存,但是发现对应大小的内存已经没有了,那么伙伴系统会从16KB的链表中查找一个空闲内存块,分成两个8KB大小,把其中的一个8KB大小返回给申请者使用,剩下的8KB放到8KB对应的内存块链表中进行管理。更坏的一种情况是,系统发现16KB大小的连续内存页已经没有了,那么以此会向更高的32KB链表中查找,如果找到了空闲内存块,那么就把32KB分成一个16KB和两个8KB,16KB的内存块放到16KB的链表进行管理,两个8KB的内存块一个返回给申请者,另一个放到8KB大小的链表进行管理
当释放内存时,会扫描对应大小的内存块链表,查看是否存在地址能够连续在一起的内存块,如果发现有,那么就合并两个内存块放置到更大一级的内存块链表上,以此类推。比如我们释放8KB大小的内存,那么会从对应的链表扫描是否有能够合并的内存块,如果有另一个8KB大小的内存和我们使用的内存地址连续,那么就合并它们组成一个16KB大小的内存块,然后接着扫描16KB大小的内存块链表,继续查找合并的可能,以此类推下去
哈希算法
上面两种算法都是将空闲分区根据分区大小进行分类,对于每一类具有相同大小的空闲分区单独设立一个空闲分区表,查找时如果表项比较多会显著增加时间开销。哈希算法就是利用哈希快速查找的优点,以及空闲分区在可利用空闲区表中的分布规律建立哈希函数,构造一张以空闲分区大小为关键字的哈希表,该表的每一个表项记录了一个对应的空闲分区链表表头指针
当进行空闲分区分配时根据所需空闲分区大小,通过哈希函数计算,得到在哈希表中的位置,从中得到相应的空闲分区链表,实现最佳分配策略
4.3.6 动态可重定位分区分配
紧凑
将内存中所有大作业进行移动,使得他们全部邻接,这种方式叫紧凑。但是这种方式带来的问题就是用户程序在内存中的位置发生了变化,为了解决这个问题,下面介绍动态重定位方法
动态重定位
地址变换过程是在程序执行期间,随着对每条指令或数据的访问自动进行的,称为动态重定位。当系统对内存使用了紧凑,而使若干程序从内存的某处移到另一处时,不需要对程序进行任何的修改,只要用该程序在内存的新起始地址去置换原来的起始地址即可
动态重定位分区分配算法
与动态分区分配算法基本相同,差别仅在于在这种分配算法中加入了紧凑
4.4 对换
4.4.1 多道程序环境下的对换技术
把内存中暂时不能运行的进程或者暂时不用的程序和数据换出到外存,腾出足够的空间,把已经具备运行条件的进程或进程所需要的程序和数据换入内存,提高吞吐量
对换的类型
- 整体对换
- 页面对换
4.5 分页存储管理方式
如果允许一个进程直接分散的装入许多不相邻接的分区中,便可充分利用内存空间,无须紧凑。基于这一思想产生了离散的分配方式
- 分页存储管理方式
- 分段存储管理方式
- 段页式存储管理方式
4.5.1 分页存储管理的基本方法
页面和物理块
页面:将进程的逻辑地址空间分成若干页,并为各页加以编号。相应的,也把内存的物理地址空间分成若干块,同样加以编号
页面大小:页面过小可以减少内存碎片,有利于内存利用率提高,但是另一方面会造成每个进程占用较多页面,导致进程页表过长,占用内存。此外,还会降低换出效率。如果页面过大又会使页内碎片增大,因此页面大小应该选择适中。且页面大小应该是2的幂
地址结构
包含页号和位移量
对某特定机器,其地址结构是一定的。若给定一个逻辑地址空间中地址为A,页面大小为L,则页号和页内地址d可按照下式求得
页表
在分页系统中,允许进程的各个页离散地存储在内存地任一物理块中,为保证进程仍然能够正确地运行,即能在内存中找到各个页面所对应地物理块,系统又为每个进程建立了一张页面印象表,简称页表,它地作用是实现从页号到物理块号的地址映射
4.5.2 地址变换机构
将逻辑地址转变为物理地址
基本地址变换(直接地址映像)
借助页表、页表寄存器完成作业逻辑地址(虚地址)到内存物理地址的变换
具有快表的地址变换
增设若干具有并行查询能力的特殊高速缓冲寄存器(联想寄存器\快表),保存当前执行进程的部分\全部页表表目,
具体流程为:查快表,找到则访问内存直接得物理地址,没找到则先访问内存查页表再访问内存查到物理地址
分页基本地址变换示例
具有快表的地址变换示例
4.5.3 访问内存的有效时间
指的是从进程发出指定逻辑地址的访问请求,经过地址变换,到在内存中找到对应的实际物理地址单元并取出数据,所需要花费的总时间
4.5.4 两级和多级页表
两级页表
两级页表采用离散分配的方式,将页表进行分页,然后将各个页面分别存储在不同的物理块中以解决连续存储的问题。一级页表被分成了若干个页面分别存储在不同的物理块中,另外一级页表又叫做外层页表,它是用来存储刚刚所划分的各个页面的首地址,通过它我们就可以知道各个页面所处的位置。
以32位逻辑地址空间的分页系统为例,如果采用一级页表,那么页表所占用的内存空间是1MB,而且必须是连续的。现在我们将页表等分成1024份,即产生了1024个页面,并且每个页面有1024个表项(每个表项1B,即每个页面1KB),存储的是页号与物理块号的映射关系;然后我们建立外层页表,由于有1024个页面,所以外层页表有1024个表项(每个表项1B,外层页表1KB),存储的是各个页面的首地址。这样我们就实现了一个两级页表,由于两级页表采用了离散分配的方式,外层页表和每个表项所对应的页面分别存储在不同的物理块中,解决了需要连续存储的问题。
多级页表
32位机上采用两级页表结构是合适的,64位机上不一定,因此推出多级页表
4.6 分段存储管理方式
4.6.1 分段存储管理方式的引入
方便编程
通常用户把自己的作业按照逻辑关系划分为若干段,每段都从0开始编址,并且有自己的名字和长度。因此我们需要访问的逻辑地址是由段名和段内偏移量决定的,不仅使程序员方便编程,也使程序非常直观
信息共享
为该被共享过程建立一个独立的段,极大的简化了共享的实现
信息保护
分页难以对页面实行统一保护,分段可以更有效的实现对信息的保护
动态增长
数据量增加导致数据段动态增长,分段存储可以较好的解决该问题
动态链接
动态链接以目标程序作为链接的基本单位,因此分段存储管理方式适合动态链接
4.6.2 分段系统的基本原理
分段
作业地址空间被划分为若干段,每段定义了一组逻辑信息,分段地址中的地址具有如下信息
段表
段表记录了段与内存位置的对应关系,保存在内存中,基址及长度由段表寄存器给出。
地址变换机构
分页和分段的主要区别
页是信息的物理单位
页的大小固定且由系统决定
分页的用户程序地址空间是一维的
4.6.3 信息共享
允许若干进程共享一个或多个分段,且对段的保护也十分简单易行
4.6.4 段页式存储管理方式
将用户程序分成若干段,并为每个段赋予一个段名,把每个段分成若干页,地址结构包括段号、段内页号和页内地址三部分
地址变换过程
欢迎指正。