一、定义
程序:一个指令序列(早期计算机仅支持单道程序);内存中存放在程序段和数据段中
引入多道程序技术后,为了方便执行程序并发,引入了进程、进程实体的概念
1.进程实体
每个程序执行之前,会为其在内存中创建一个数据结构--进程控制块(PCB),用以描述进程的各种信息。
进程实体 = 程序段 + 数据段 + PCB 一般进程实体可以简称为进程。但是进程的创建和撤销实质是操作其PCB。(PCB是进程存在的唯一标志)
2.进程
定义:
①进程是程序的一次执行过程
②进程是一个程序及其数据在处理机上顺序执行时发生的活动
③进程是具有独立功能的程序在数据集合上运行的过程
④进程是进程实体的运行过程,是系统资源分配和调度的一个独立单位
进程是一个动态的过程。
3.进程和进程实体的区别
进程是动态的、进程实体是静态的(但如果不加以区分,默认进程实体就是进程,也可以说: 进程 = 程序段 + 数据段 + PCB)
二、组成
进程的组成
程序段:程序代码存放处
数据段:程序运行产生的临时数据
PCB:操作系统用于管理进程的各种信息
PCB的组成
进程描述信息
进程标识符PID:进程创建时,由操作系统分配的唯一的ID,用于区分进程
用户标识符UID:用来标识进程所属的用户
进程控制信息
进程当前状态、进程优先级
资源分配清单
程序段指针、数据段指针、键盘、鼠标
处理机信息
各种寄存器值:用于在切换时保存当前程序的执行进度。
三、组织方式
1.链接方式
按照进程状态将PCB分为多个队列、系统持有指向各个队列的指针
执行指针:只会执行一个PCB(同时处理的进程仅能有一个)
就绪队列指针:该队列会将优先级高的进程放在队头
阻塞队列指针:会区分其阻塞原因再分出多个队列
2.索引方式
根据进程状态建立数张索引表、系统持有指向各索引表的指针
四、特征
动态性:是程序的一次执行过程;(最基本的特征)
并发性:内存中存在多个进程实体、可以并发执行
独立性:独立运行、独立获取资源、独立接受调度(基本单位)
异步性:各自独立、且不可预知的向前推进;系统会提供“进程同步机制”来解决异步问题
结构性:每个进程都会配置一个PCB
五、进程的状态和转换
1.状态
运行态:占用CPU进行运行(每个核每次仅能运行一个进程)
就绪态:已具备运行条件,但是CPU没有空闲,暂时不能运行(处于此状态下,进程拥有除CPU以外的全部资源)
阻塞态:又称等待态,因等待某个事务而无法运行
创建态:系统正在为进程分配资源、初始化PCB
终止态:系统正在回收资源、撤销PCB
2.状态间的转换
六、进程控制
1.定义
主要功能是对系统中所有进程实施管理(创建、撤销、状态转换)
2.实现
需要执行PCB内容的修改,并将其放入对应的队列中。同时需要分配/撤销资源;保存/恢复程序运行环境。
使用原语来实现进程控制。特点:不允许中断,此操作也被称为原子操作;原语采用“关中断指令”和“开中断指令”实现(中断关闭时不会响应其他代码)
开关中断指令仅运行在核心态下(操作系统内核的一部分,特权指令)
3.原语
原语的功能:
1.更新PCB中的信息
a.所有的进程控制原语必然修改进程状态
b.剥夺当前运行进程的CPU使用权必然需要保存其运行环境
c.进程开始前必须恢复其环境
2.将PCB插入合适的队列
3.分配/回收资源
系统提供的原语
创建原语: 1.申请空白PCB
2.为新进程分配资源
3.初始化PCB
4.将PCB插入就绪队列
会引发创建的事件: 1.用户登录 3.提供服务
2.作业调度 4.应用申请(子进程)
撤销原语: 1.找到终止进程的PCB
2.若进程正在运行,立刻剥夺其CPU
3.终止其所有子进程
4.回收系统资源(还给父进程/系统)
5.删除PCB
会引发撤销的事件: 1.正常结束 2.异常结束 3.外界干扰
阻塞原语: 1.找到阻塞队列中对应的PCB
2.保护运行现场,将PCB状态设置为阻塞态,暂停进程运行
3.将PCB插入等待队列
会引发阻塞的事件: 1.需要等待资源分配 2.需要等待其他进程配合
唤醒原语: 1.找到等待队列中对应的PCB
2.将PCB从等待队列中移除,设置进程为就绪态
3.将PCB插入就绪队列,等待其调用
会引发唤醒的事件: 1.等待事件发生
阻塞和唤醒必定成对出现
七、进程通信
进程间的信息交换(各进程拥有独立的内存和地址空间,一般来说不能直接访问其他进程的资源)
1.共享存储
操作系统为进程分配共享空间,指定的进程都可以访问;但是这种共享是互斥的(同一时间段只能有一个进程访问)--互斥通过系统提供的工具实现。
基于数据结构的共享
速度慢、限制多,是一种低级的通信方式
基于存储区的共享
系统仅提供内存区域,具体内容由进程协定。速度更快、是一种高级通信方式。
2.消息传递
以格式化的消息为单位。通过发送消息和接收消息两个原语来实现
消息结构分为:消息头
发送进程ID、接收进程ID、消息类型、消息长度等格式化信息
消息体
通信方式: 直接通信方式:消息直接挂到接收进程的消息缓冲队列上
间接通信方式:消息需先发送到中间实体(信箱)
3.管道通信
管道是一种特殊的共享文件(又称pipe文件,是内存中一个大小固定的缓冲区)
单个管道仅能实现半双工;若想实现全双工的话必须设置两个管道。
各进程互斥的访问管道。
只有当管道写满时,进程才能读数据(write被阻塞);只有管道中的数据被读完后,另一个进程才能写数据(read被阻塞)。数据以字符流的形式写入管道。
管道内的数据一旦被读出即被抛弃,所以一次只能是一个进程读管道内的数据。
八、线程&线程模型
1.线程
进程是一个程序的顺序执行,但复杂的程序功能不能由程序一次执行实现。所以引入了线程来增加并发度(线程之间可以并发)。
引入线程后的变化
①资源分配以进程为单位,调度以线程为单位(之前也是进程)
②线程之间能并发(之前是仅进程之间能并发)
③进程间的切换需要切换运行状态,系统开销较大。线程在统一进程内切换无需切换运行环境,可减小系统开销。
线程的属性
①线程是处理机调度的单位
②各个线程可以独占不同的CPU
③每个线程都拥有线程ID和线程控制块(TCB)
④线程也拥有就绪、阻塞、运行三种基本状态
⑤线程几乎不拥有系统资源、同一进程内的线程共享进程的资源
⑥同一进程内的线程通讯无需系统干预
⑦同一进程内的线程切换无需引起进程切换,反之会引起进程切换
⑧切换同一进程内的线程开销很小,反之开销较大
2.线程的实现
用户级线程
由应用程序实现,线程切换在用户态下即可实现(在用户看来是多线程,而从操作系统来看仅能看到进程)
内核级线程
由系统内核实现,线程的切换需要在核心态下进程
也可以进行组合,但是仅有内核级线程才是处理机分配的单位。
3.多线程模型
在同时运行用户级线程和内核级线程的系统中,两种线程的映射问题引出了多线程模型。
多线程模型的分类
①多对一模型
优点:用户级线程切换,无需切换至核心态、系统开销少。
缺点:当一个用户级线程被阻塞后,其他进程也会被阻塞。并发度不高。且多个线程不可在多核处理机上并发运行。
②一对一模型
优点:一个线程被阻塞后不会影响其他线程,并发能力强,并可以在多核处理机上并发。
缺点:线程的切换需要先切换至核心态,系统开销大。
③多对多模型
优点:克服了多对一模型并发度不高和一对一模型系统开销大的缺点。
九、处理机调度
1.基本概念
按照一定算法选择一个进程,将处理机分配给它。
2.调度的三个层次
①高级调度
又称作业调度。按照一定的原则从外存上处于后备队列的作业中挑选一个/组,给他们分配资源,建立PCB。使它们获得竞争处理器的权利。
实际上是外存和内存间的调度,作业调入时建立PCB,调出时撤销PCB。(程序运行中仅会发生一次高级调度)
②中级调度
又称内存调度。 引入虚拟存储后,可以将暂时不能运行的程序调至外存等待,等其具备运行条件时再调入内存执行。
目的:提高内存利用率和系统吞吐量。
进程被调至外存等待的状态为挂起状态,但是PCB不会一起外调而是会常驻内存,被挂起的进程PCB会被放入挂起队列中(用来监控、管理对应的进程)。(程序运行中会发生多次中级调度)
挂起状态可以分为:就绪挂起、阻塞挂起。引入调度后,进程的五态模型将会变为七态模型
③低级调度
又称进程调度。按照规则/算法从就绪队列中选取一个进程将处理机分配给它。
进程调度是一种最基本的调度,一般操作系统必须配置进程调度。
进程调度的频率极高。
3、进程调度的时机、切换、过程、实现方式
①调度时机
需要进行切换的情况:当前运行的进程主动/被迫放弃处理机。
主动放弃:正常终止;异常终止;请求阻塞
被迫放弃:时间片用完;加急任务;更高优先级的进程进入就绪队列
不能进行进程切换的情况: 1.处理中断的过程中
2.进程在操作系统内核临界区中(普通临界区是可以进行切换的)
临界区的访问是互斥的,内核临界区是用来访问某种内核数据结构。
3.在原子操作过程中
②调度方式
非剥夺调度方式(非抢占方式)只允许进程主动放弃处理机,直到进程终止/进入阻塞态前都不会处理其他进程。
实现简单且系统开销少;但是无法及时处理紧急任务,适合早期批处理机。
剥夺调度方式(抢占方式)如果有更紧急的任务到来会立即暂停正在执行的进程,将处理机分配给更紧急的进程。
可以优先处理紧急任务(实现按时间片轮流执行的功能),适合于分时/实时操作系统。
③进程切换过程
狭义的进程调度是指从就绪队列中选中一个要运行的进程(可以是刚刚暂停的进程/其他进程,如果是其他进程则需要进行进程切换)
广义的进程调度包含选择一个进程和进程切换。
进程切换是指两个进程交接处理机的过程。
4.调度算法
①调度算法的评价指标
利用率 = 忙碌时间 / 总时间(用来衡量一个设备的效率)
吞吐量 = 总共完成的作业道数 / 总共完成的时间
周转时间 = 作业完成时间 - 作业提交给系统的时间
平均周转时间 = 各作业周转时间之和 / 作业数
带权周转时间 = (作业完成时间 - 作业提交时间) / 作业实际运行的时间
带权周转时间必定大于1;带权周转时间和周转时间都是越小越好。
等待时间 = 作业等待处理机状态的时间之和
进程的等待时间 = 进程建立后等待被服务的时间之和,等待I/O完成期间实际上是被处理机服务的,并不记入等待时间
作业的等待时间 = 建立进程后的等待时间 + 作业在外存后备队列中等待的时间
响应时间 = 提交请求到首次响应的时间
②各种调度算法
1.先来先服务(FCFS)
按照作业/进程到达的先后顺序进行服务
非抢占式算法
优点:公平、算法实现简单
缺点:对于短进程/作业不利(带权周转时间过长)
不会导致饥饿
2.短作业优先(SJF)
为了追求更短的平均等待时间和带权周转时间
最短的进程/作业优先得到服务(要求服务时间最短)
默认为非抢占式;也有抢占式版本:最短 剩余时间 优先算法(SRTN)
优点:“最短”的平均等待时间、平均周转时间
缺点:不公平,对短作业有利,对长作业不利
可能产生长作业饥饿,若一个进程/服务一直得不到服务就会产生 饿死
3.高响应比优先(HRRN)
综合考虑作业/进程等待时间和要求服务的时间
每次调度时先精算各进程/作业的响应比。选择响应比高的进行服务
响应比 = (等待时间+要求服务时间)/要求等待时间 <必定大于1>
非抢占式
结合了FCFS和SJF的优点,可以避免长作业饥饿问题(等待时间上升会导致响应比上升)
不会造成饥饿
4.时间片轮转(RR)
公平、轮流地为各个进程服务,让每个进程在一定时间间隔内都得到响应
按照进程到达就绪对立的顺序,轮流的让各进程执行一个时间片,若一个时间片未完成会剥夺处理机,将其排到就绪队列队尾
仅用于进程调度
抢占式算法;由时钟装置发出时钟中断来通知CPU时间片到了
时间片不能太小,太小会导致系统花大量资源来进行进程切换
时间片不能太长,会造成其退化为先来先服务算法
设置时间片大小时,需让切换进程造成的开销不超过1%
优点:公平、响应快、适用于分时操作系统
缺点:进程切换会有一定开销;不区分任务的紧急程度
不会造成饥饿
5.优先调度算法
根据任务的紧急程度/优先级来决定处理顺序
即可用于进程调度,也可用于作业调度
抢占式和非抢占式都有;区别在于检查时机不同(抢占式需要在就绪队列变化时检查,非抢占式仅需在进程释放时检查)
就绪队列未必只有一个,部分操作系统会按照优先级组织队列。优先级高的会排在更靠近队头的位置
根据优先级是否动态改变分为:静态优先级、动态优先级
优先级的设置: 系统进程 > 用户进程 前台进程 > 后台进程
操作系统更偏好I/O型进程(I/O繁忙型进程)--对应的是计算型进程(CPU繁忙型进程)
动态优先级的调整:从公平、提升资源利用率等角度考虑。
优点:用优先级区分紧急、重要程度,适用于实时操作系统,灵活的调整各作业/进程的偏好程度
缺点:可能导致饥饿(源源不断的到来高优先级)
6.多级反馈队列调度算法
对其他调度算法的折中权衡
①设置多级就绪队列(优先级从高到低,时间片从小到大)
②新进程到达时先进入1级=队列,按FCFS原则排队等待分配时间片,若在一个时间片能未完成则进入一下级队列
③k级队列空了后才会为k+1级队列分配时间片
抢占式算法:k级队列运行时,上级队列中进入一个新进程则会抢断,将原来的进程放入k级队列的队尾
优点:综合了FCFS,RR,SPF等算法的优点
会造成饥饿
十、进程的同步&互斥
1.进程同步
直接制约关系,任务需要多个进程系统完成(有工作次序关系)
2.进程互斥
间接制约关系,某一进程访问某临界资源时,其他进程要访问就只能等待这个进程访问完成。
对临界资源的访问从逻辑上分为以下几部分:
1.进入区:负责检查临界区是否可进入,设有“正在访问临界资源的标志”
2.临界区:访问临界资源的代码
3.退出区:负责解除“正在访问临界资源的标志”
4.剩余区:其他处理
实现进程互斥时需要遵循以下原则:
1.空闲让进:临界区空闲时,可以允许一个请求进入临界区的进程立即进入临界区
2.忙则等待:......
3.有限等待:对请求访问的进程,应保证在有限时间内进入临界区
4.让权等待:当进程不能进入临界区时,应立刻释放处理机,防止进程忙等待
进程互斥的软件实现
①单标志法
本进程访问临界区后将权限交给另一进程(进程之间交接)
设置一个标志,表示能访问临界区的进程ID号(由上个进程进行修改)
缺陷:违背空闲让进原则
②双标志先检查法
设置一个bool数组,对应 i 位置表示 i 进程想要进入临界区的意愿。每个进程进入临界区前会检查数组中是否有其他标志,如果没有就将自己位置的flag设置为ture并开始访问临界区。
缺陷:在某些顺序下可能违背“忙则等待”原则,原因在于进入临界区时,检查和上锁是两步执行的。
③双标志后检查法
解决双标志先检查法“检查和上锁”分两步的问题。将上锁放在了检查的前面。
缺陷:虽然解决忙着等待,但是违背了空闲让进和有限等待原则,可能造成饥饿
④Peterson算法
基于双标志后检查法,当两个进程都想访问临界区的时候尝试让进程主动让对方先使用临界区。
缺陷:不遵循“让权等待”,容易出现忙等
进程互斥的硬件实现方法
①中断屏蔽方法
利用“开/关中断指令实现”(利用原语不可被中断的特性)
执行步骤:关中断->访问临界区->开中断(关中断后不允许当前进程被切换)
优点:实现起来简单高效
缺点:不适用于多处理机;只适用于操作系统内核,不适用于用户进程(开关中断指令仅能运行在内核态)
②TestAndSet(TS指令)
利用硬件实现,执行的过程不允许被中断
执行步骤
bool TestAndSet(bool *lock)
{
bool old;
old = *lock; //old用来存放lock的原值
*lock = true; //无论是否上锁都将lock设置为ture
return old; //返回原lock指
}
//实现TSL互斥
while(TestAndSet(&lock)); //上锁并检查
//临界区代码
lock=false;
//剩余区代码
相较于软件方法,TSL指令把“上锁”和“检查”使用硬件实现变为了原子操作
优点:实现简单,无需像软件实现那样严格检查是否有逻辑漏洞;适用于多处理机。
缺点:不满足“让权等待”,可能造成进程忙等
③Swap指令(SCHG指令)
利用硬件实现,执行的过程不允许被中断
执行步骤
//swap指令的作用是交换两个变量的值
Swap(bool *a,bool *b)
{
bool temp;
temp = *a;
*a = *b;
*b = temp;
}
//以下是用Swap指令实现互斥的算法逻辑
//lock表示当前临界区是否加锁
bool old = true;
while(old == true)
Swap(&lock , &old);
//临界区代码
lock = false;
//剩余区代码
优点:实现简单,无需像软件实现那样严格检查是否有逻辑漏洞;适用于多处理机。
缺点:不满足“让权等待”,可能造成进程忙等
十一、信号量机制
用户可以通过操作系统提供的一对原语对信号量进行操作,从而实现进程的互斥/同步
信号量:一个变量,可以用一个信号量来表示系统中某种资源的数量
使用的原语为wait(S)和signal(S),S是信号量,是调用时传入的参数,可以简称为P(S),V(S)操作
1.信号量分类
①整型信号量
用一个整型数的变量作为信号量,用来表示系统中某种资源的数量
进程P0
...
wait(S); //进入区,申请资源
使用资源 //临界区,访问资源
signal(S); //突出区,释放资源
int S = 1; //初始化整型信号量S,表示当前系统可调用的资源数仅为1
void wait(int S){
while(S<=0); //如果资源数不够,就一直循环等待
S = S - 1; //占用一个资源
}
void signal(int S){
S = S + 1; //使用完成,释放资源
}
检查、上锁一气呵成,避免了并发、异步的问题;存在的问题:不满足“让权等待”,会发生忙等。
②记录型信号量
为了解决整型信号量出现忙等的问题。
typdef struct{
int value; //剩余资源数
struct process *L; //等待队列
}semaphore;
void wait(semaphore S){
S.value--; //申请资源
if(S.value<0){ //检查是否还有资源(可以为负)
block(S.L); //将进程阻塞,挂载到阻塞队列中
}
}
void signal(semaphore S){
s.value++; //释放资源
if(S.value <=0){ //是否有资源可以使用
wakeup(S.L); //唤醒等待队列中的进程
}
}
遵循了“让权等待”,不会出现忙等。
2.信号量机制的应用
①实现进程互斥
1.分析并发进程的关键活动,划定临界区。
2.设置互斥信号量mutex,初值为1
3.执行P、V操作
!!!对不同的临界资源,需要设置不同的互斥信号量。
②实现进程同步
让本来异步并发的进程互相配合,有序推进
1.分析需要实现“同步关系”的地方
2.设置同步信号量S,初始化为0
3.在“前操作”之后执行V(S)
4.在“后操作”之前执行P(S)
③实现进程的前驱关系
1.为每一对前驱关系各设置一个同步变量
2.前操作之后执行一个V操作
3.后操作之前执行一个P操作
十二、信号量机制实现进程互斥的经典问题
1.生产者-消费者问题
问题描述:生产者进程将生产的产品(数据),放入缓冲区,消费者进程从缓冲区取出数据,缓冲区的访问必须互斥。
实现:①前操作之后执行一个V操作 ②后操作之前执行一个P操作
本质上是同步问题。需要实现三对PV操作。
实现互斥的P操作必须放在实现同步的P操作之后,否则可能发生死锁。
V操作的执行顺序无所谓
非必要代码不建议放入临界区代码中(如使用产品),会增大使用临界区的时间,不利于资源的利用。
2.多生产者-多消费者问题
代码实现
!!!即使不设置互斥信号量mutex,也不会出现同时访问的现象。(原因是本问题中的缓冲区大小仅能为1)。若缓冲区大小大于1,则可能出现生产者进程相互覆盖数据的情况。
3.吸烟者问题
实质:可以生产多个产品的单生产者。
4.读者-作者问题
潜在问题,如果一直有读进程就可能让写进程出现饿死的情况。 解决↓
核心思想:设置了count计数器,第一个/最后一个需要进行不同的处理。
5.哲学家就餐问题
当每个进程需要同时持有两个临界资源的时候可能产生死锁。
十三、管程
信号量机制的缺陷:编写程序困难、容易出错。
管程是一种高级的同步机制,让用户不需要关注PV操作。
1.管程组成和特征
组成:①局部于管程的共享数据结构
②对该数据结构进行操作的一组过程(函数)
③对局部于管程的共享数据设置初始值的语句
④管程有一个名字
特征:①局部于管程的数据只能被内部过程访问
②一个进程只有通过管程才能访问内部共享数据
③每次仅允许一个进程在管程内部执行
2.以管程解决生产者-消费者问题
将PV操作封装在管程中(类似于class),PV功能由编译器实现。
正常情况下,各消费者进程依次执行insert即可;如果出现了需要同步的消费者进程则需要先调用remove。
可以在管程中设置条件变量及等待/唤醒操作以解决同步问题(让一个进程/线程在条件变量上等待)
十四、死锁
1.什么是死锁
在并发环境下,各进程因竞争资源而造成的一种互相等待对方手里的资源,导致各进程都阻塞,都无法向前推进的现象。
2.死锁、饥饿、死循环的区别
死锁:互相等待资源造成全部阻塞,无法向前推进
一定处于阻塞态,且至少是两个以上的进程
饥饿:长期得不到资源,无法向前推进
可能处于阻塞态(得不到I/O),也可能处于就绪态(得不到CPU),可能只有一个进程
死循环:在执行过程中无法跳出循环,无法向前推进
死循环可能是运行态,死锁和饥饿是资源分配造成的,死循环是代码逻辑错误造成的。
3.发生死锁
需要同时满足以下四个条件,缺一不可(不可剥夺的资源分配不合理可能导致死锁)
①互斥条件:对必须互斥使用的资源进行争抢
②不可剥夺条件:不能强行剥夺资源
③请求和保持条件:至少持有一个资源,又提出新的资源请求,且保持已持有的资源不释放
④循环等待条件:存在进程资源的循环等待链(发生死锁一定有循环等待,但是发生循环等待不一定会出现死锁)
发生死锁的时机:
①对系统资源的竞争
②进程推进顺序非法
③信号量使用不当造成死锁
4.死锁的处理策略
①预防死锁
预防死锁是一种静态策略
Ⅰ破坏互斥条件:将互斥使用的资源改造为允许共享使用(如SPOOLing技术)
缺点:但是为了系统安全,很多地方必须保持互斥性,所以无法被改造
Ⅱ破坏不剥夺条件:
方案一:(主动释放)当进程请求新的资源得不到满足时,它必须立刻释放掉保持的所有资源,待以后需要的时候再申请
方案二:(系统剥夺)当进程需要的资源被其他进程占有时,由操作系统协助,强行剥夺锁需要的资源,但是需要考虑进程优先级
缺点:①实现起来复杂;②资源释放会造成前一阶段工作的失效,因此仅适用于易保存和恢复的资源,如CPU;③反复申请和释放资源会增加系统开销,降低系统吞吐量;④采用方案一时,可能造成进程饥饿;
Ⅲ破坏请求和保持条件:采用静态分配方法,在进程运行之前一次申请完它全部的资源,未满足条件前不投入运行
缺点:有的资源可能仅被需要极短的时间,但是进程一直持有会降低资源利用率;此外这种策略也可能导致饥饿。
Ⅳ破坏循环等待条件:采用顺序资源分配法。首先给系统中的资源编号,规定每个进程必须按编号递增的顺序请求资源,同类资源(编号相同)一次申请完。
原理:只能出现小编号进程等待大编号进程,故破坏了反向链条,不会出现循环等待
缺点:①不方便新增设备;②实际使用资源的顺序与编号顺序不一致可能造成资源浪费;③必须按规定次序申请资源,用户编程麻烦;
②避免死锁
是一种动态策略。
安全序列:指系统按照这种序列分配资源,则每个进程都能顺利完成。只要能找出一个安全序列,系统就是安全状态。安全序列可能有多个。
若分配资源后,系统找不出任何一个安全序列,系统就会进入不安全状态,有可能发生死锁。(进入不安全状态未必会死锁)
在资源分配前预判这次分配会不会导致系统进入不安全状态,以此决定是否答应资源请求分配,说银行家算法的核心思想。
③死锁的检测和解除
Ⅰ死锁的检测
①用某种数据结构来保存资源的请求和分配信息
②提供一种算法,利用上述信息检测系统是否已经进入死锁状态
若资源分配图最终能消除所有的边,则称此图是完全可简化的。此时一定没有发生死锁。
Ⅱ死锁的解除
用死锁检测算法化简后,还连着边的进程即为死锁进程,解除方法如下:
①资源剥夺法:挂起某些死锁进程并抢占其资源,分配给所需要进程(但应防止其长时间得不到资源产生饥饿)
②撤销进程法:强制撤销部分/全部死锁进程,剥夺其运行资源(方法简单粗暴但是可能付出较大的代价)
③进程回退法:选择一个/多个死锁进程,让其回退到足矣避免死锁的地步(要求系统记录进程历史并设置还原点)
选择进程的考虑:
①进程优先级 ②已执行时间 ③剩余时间 ④已使用资源 ⑤进程是交互式还是批处理式