PCB 是给 操作系统用的,程序段、数据段 是 给进程自己用的
一个 进程实体(进程映像) 由 PCB、程序段、数据段 组成
进程是 动态 的,进程实体(进程映像) 是 静态 的。
进程 是进程实体的 运行过程,是系统进行 资源分配 和 调度 的一个独立单位
一个进程被“调度”,就是指操作系统决定让这个进程上CPU运行
当进程被创建时,操作系统会为其分配一个 唯一的、不重复 的“身份证”——PID(Process ID、进程ID)
进程控制块(PCB):
PCB是进程存在的唯一标志,当进程被创建时,操作系统为其创建PCB,当进程结束时,会回收其PCB
这些信息被保存在一个数据结构 PCB 中(Process Control Block)中,即 进程控制块
操作系统需要对各个并发运行的进程进行管理,但凡管理时所需要的信息,都会被放在PCB中
动态性:进程是程序的一次执行过程,是动态地产生、变化和消亡的
动态性是进程最基本的特征
并发性:内存中有多个进程实体,各进程可并发执行
独立性:进程是能独立进行、独立获得资源、独立接受调度的基本单位
异步性:各进程按各自独立的、不可预知的速度向前推进,操作系统要提供“进程同步机制”来解决异步问题
异步性会导致并发程序执行结果的不确定性。
结构性:每个进程都会配置一个PCB。结构上看,进程由程序段、数据段、PCB组成
进程的 组成 讨论的是 一个进程内部 由哪些部分构成的问题
进程的 组织 讨论的是 多个进程之间 的组织方式问题
链接方式
索引方式
就绪态、运行态、阻塞态是进程的三种基本状态
进程PCB中会有一个变量state来表示进程的当前状态
创建态(New,又称新建态)
进程正在被创建,在这个阶段系统会分配资源、初始化PCB
就绪态 (Ready)
进程创建完成后进入“就绪态”,此时进程具备运行条件,但由于没有空闲的CPU,暂不能运行
运行态 (Running)
占有CPU,并在CPU上运行
注:单核处理机:每一时刻最多只有一个进程处于运行态
双核处理机:每一时刻最多可以同时有两个进程处于运行态
阻塞态 (Waiting/Blocked,又称等待态)
因等待某一事件而暂时不能运行
注:如操作系统分配打印机、等待读磁盘操作的结果。
为提高CPU利用率,需先将其他进程所需资源分配到位,才能得到CPU的服务。
就绪态:有资源、欠CPU
阻塞态:欠资源、欠CPU
终止态(Terminated,又称结束态)
进程正在从系统中撤销,操作系统会回收进程拥有的资源、撤销PCB
就绪态——>运行态
进程被调度
运行态——>就绪态
时间片到,或CPU被其他高优先级的进程抢占
运行态——>阻塞态
等待系统资源分配,或等待某事件发生(主动行为)
阻塞态——>就绪态
资源分配到位,等待的事件发生(被动行为)
创建态——>就绪态
系统完成创建进程的相关操作
运行态——>终止态
进程运行结束,或运行过程中遇到不可修复的错误
概念:进程控制的主要功能是对系统中的所有进程实施有效的管理,它具有创建新进程、撤销已有进程、实现进程状态转换等功能
如何实现进程控制——原语(运行在 核心态)
原语的特点是执行期间 不允许中断 ,只能一气呵成。
这种不可被中断的操作即 原子操作 。
原语采用 “关中断 指令”和 “ 开中断 指令”实现
原语做的三类事:
更新PCB中信息
eg:
将PCB插入合适的队列
分配/回收资源
阻塞原语和唤醒原语必须成对使用
基于数据结构 的共享:
比如共享空间里只能放一个长度为10的数组。
这种共享方式速度慢、限制多,是一种 低级通信 方式。
基于存储区 的共享:
在内存中画出一块共享存储区,数据的形式、存放位置都由进程控制,而不是操作系统。
相比之下,这种共享方式速度更快,是一种 高级通信 方式。
管道只能采用 半双工通信 ,某一时间段内只能实现 单向的传输;
如果要实现 双向同时通信,则 需要设置两个管道。
各进程要 互斥 地访问管道。
数据以 字符流 的形式写入管道,当 管道写满 时,写进程 的write() 系统调用将被 阻塞,等待读进程将数据取走。
当读进程将数据全部取走后,管道变空,此时 读进程 的read() 系统调用将被 阻塞。
如果 没写满,就不允许读。
如果 没读空,就不允许写。
数据一旦被读出,就从管道中被抛弃,这意味着 读进程最多只能有一个,否则可能会有读错数据的情况。
进程间的数据交换以 格式化的消息(Message)为单位。
进程通过操作系统提供的 “发送消息/接收消息” 两个 原语 进行数据交换。
直接通信方式
消息直接挂到接收进程的 消息缓冲队列 上
间接通信方式
消息要先发送到中间实体(信箱)中,因此也称 “信箱通信方式”。
eg:计网中的电子邮件系统。
引入线程机制后的变化:
线程的属性:
用户级线程(User-Level Thread,ULT)
历史背景:
例:
很多编程语言提供看强大的线程库,可以实现线程的创建、销毁、调度等功能。
1、用户级线程由 应用程序 通过线程库实现,所有的 线程管理工作 都由 应用程序负责(包括线程切换)。
2、用户级线程中,线程切换 可以在 用户态下即可完成,无需操作系统干预。
3、在用户看来,是有多个线程。但是在操作系统内核看来,并意识不到线程的存在。用户级线程 就是 “从用户视角看能看到的线程”
4、优缺点:
优点:用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高。
缺点:当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高。多个线程不可在多核处理机上并行运行。
内核级线程(Kernel-Level Thread,KLT,又称“内核支持的线程”)
1、内核级线程的管理工作 由 操作系统内核 完成。
2、线程调度、切换等工作都由内核负责,因此 内核级线程的切换 必然需要在 核心态 下才能完成。
3、操作系统会为每个内核级线程建立相应的TCB(Thread Control Block,线程控制块),通过TCB对线程进行管理。“内核级线程” 就是 从操作系统内核视角看能看到的线程。
4、优缺点:
优点:当一个线程被阻塞后,别的线程还可以继续执行,并发能力强。多线程可在多核处理机上并行执行。
缺点:一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态,因此线程管理的成本高,开销大。
一对一 模型 :一个用户级线程映射到一个内核级线程。每个用户进程有与用户级线程同数量的内核级线程。
(优缺点见内核级线程的优缺点)
多对一 模型:多个用户级线程映射到一个内核级线程。且一个进程只被分配一个内核级线程。
(优缺点见用户级线程的优缺点)
多对多 模型:n用户级线程映射到m内核级线程( n ≥ m )。每个用户进程对应m个内核级线程。、
克服了多对一模型并发度不高的缺点(一个阻塞全体阻塞);
克服了一对一模型中一个用户进程占用太多内核级线程,开销太大的缺点。
高级调度
高级调度(作业调度) :
按一定的原则从外存的作业后备队列中挑选一个作业调入内存,并创建进程。每个作业只调入一次,调出一次。作业调入时会建立PCB,调出时才撤销PCB。
低级调度
低级调度(进程调度/处理机调度):
按照某种策略从就绪队列中选取一个进程,将处理机分配给它。
进程调度是操作系统中 最基本的一种调度,在一般的操作系统中都必须配置进程调度。
进程调度的 频率很高,一般几十毫秒一次。
中级调度
中级调度(内存调度):
按照某种策略决定将哪个处于挂起状态的进程重新调入内存。
一个进程可能会被多次调出、调入内存,因此 中级调度 发生的 频率 要比高级调度 更高。
三层调度的联系、对比
临界资源:
一个时间段内只允许一个进程使用的资源。各进程需要 互斥地 访问临界资源;
临界区:
访问临界资源的那段代码。
进程在 操作系统内核程序临界区 中 不能 进行调度和切换 √
会先上锁
进程处于 临界区 时 不能 进行处理机调度 ×
非剥夺方式
又称 非抢占方式。即,只允许进程主动放弃处理机。在运行过程中即便有更紧迫的任务到达,当前进程依然会继续使用处理机,直到该进程终止或主动要求进入阻塞态。
实现简单,系统开销小但无法及时处理紧急任务,适合于早期的批处理系统。
剥夺调度方式
又称 抢占方式。当一个进程正在处理机上执行时,如果有一个更重要或更紧迫的进程需要使用处理机,即立即暂停正在执行的进程,将处理机分配给更重要紧迫的那个进程。
可以优先处理更紧急的进程,也可实现让各进程按时间片轮流执行的功能(通过时钟中断)。适合于分时操作系统、实时操作系统。
"狭义的进程调度"与“进程切换”的区别:
进程切换的过程主要完成了:
1、对原来运行进程各种数据的保存;
2、对新的进程各种数据的恢复;
(如:程序计数器、程序状态字、各种数据寄存器等处理机现场信息,这些信息一般保存在进程控制块)
注意:
进程切换是有代价的,因此如果 过于频繁的 进行进程 调度、切换,必然会使整个 系统效率降低,使系统大部分时间都花在了进程切换上,而真正用于执行进程的时间减少
本小节不是考试重点,但需要理解。
CPU造价昂贵,希望让CPU尽可能多地工作
CPU利用率:
指 CPU “忙碌” 的时间占总时间的比例。
利用率:
利 用 率 = 忙 碌 的 时 间 总 时 间 利用率=\frac{忙碌的时间}{总时间} 利用率=总时间忙碌的时间
eg:
对于计算机来说,希望能用尽可能少的时间处理完尽可能多的作业
系统吞吐量
单位时间内完成作业的数量
系 统 吞 吐 量 = 总 共 完 成 了 多 少 道 作 业 总 共 花 了 多 少 时 间 系统吞吐量=\frac{总共完成了多少道作业}{总共花了多少时间} 系统吞吐量=总共花了多少时间总共完成了多少道作业
eg:
对于计算机来说,他很关心自己的作业从提交到完成花了多少时间
周转时间
是指 作业被提交给系统开始,到 作业完成为止 的这段时间间隔
它包括四个部分:
1、作业在外存后备队列上等待作业调度(高级调度)的时间
2、进程在就绪队列上等待进程调度(低级调度)的时间
3、进程在CPU上执行的时间
4、进程等待 I/O 操作完成的时间
后三项在一个作业的整个处理过程中,可能发生多次
(作业)周转时间
( 作 业 ) 周 转 时 间 = 作 业 完 成 时 间 − 作 业 提 交 时 间 (作业)周转时间=作业完成时间-作业提交时间 (作业)周转时间=作业完成时间−作业提交时间
对于用户来说,跟关心自己的单个作业的周转时间
平均周转时间
平 均 周 转 时 间 = 各 作 业 周 转 时 间 之 和 作 业 数 平均周转时间=\frac{各作业周转时间之和}{作业数} 平均周转时间=作业数各作业周转时间之和
对于操作系统来说,更关心系统的整体表现,因此更关心所有作业周转时间的平均值
带 权 周 转 时 间 = 作 业 周 转 时 间 作 业 实 际 运 行 的 时 间 = 作 业 完 成 时 间 − 作 业 提 交 时 间 作 业 实 际 运 行 的 时 间 带权周转时间=\frac{作业周转时间}{作业实际运行的时间}=\frac{作业完成时间-作业提交时间}{作业实际运行的时间} 带权周转时间=作业实际运行的时间作业周转时间=作业实际运行的时间作业完成时间−作业提交时间
带权周转时间必然≥1
带权周转时间与周转时间都是越小越好
平 均 带 权 周 转 时 间 = 各 作 业 带 权 周 转 时 间 之 和 作 业 数 平均带权周转时间=\frac{各作业带权周转时间之和}{作业数} 平均带权周转时间=作业数各作业带权周转时间之和
计算机的用户希望自己的作业尽可能少的等待处理机
等待时间
指进程/作业 处于等待处理机状态时间之和,等待时间越长,用户满意度越低。
对于 进程 来说,等待时间就是指进程建立后 等待被服务的时间之和,在等待I/O完成的期间其实进程也是在被服务的,所以不计入等待时间。
对于 作业 来说,不仅要考虑 建立进程后的等待时间,还要加上作业在外村后备队列中等待的时间。
一个作业总共需要被CPU服务多久,被I/O设备服务多久一般是确定不变的,因此调度算法其实只会影响作业/进程的等待时间。
与前面指标类似,也有“平均等待时间”来评价整体性能。
对于计算机用户来说,希望自己的提交的请求(比如通过键盘输入了一个调试命令)尽早地开始被系统服务、回应。
响应时间
指从用户 提交请求 到 首次产生响应 所用的时间
FCFS——First Come First Serve
算法思想:主要从“公平”角度考虑
算法规则:按照作业/进程到达的先后顺序进行服务
用于作业/进程调度:
用于作业调度时,考虑的是哪个作业先到达后备队列;
用于进程调度时,考虑的是哪个进程先到达就绪队列;
是否可抢占: 非抢占式的算法
优缺点:
优点:公平、算法实现简单
缺点:排在长作业(进程)后面的短作业需要等待很长时间,带权周转时间很大,对短作业来说用户体验不好。即,FCDS算法 对长作业有利,对短作业不利
是否会导致 饥饿:不会 (只要等就会轮到)
补充:饥饿:指某进程/作业长期得不到服务
例:
注意到P3的带权周转时间很大,这意味着P3本来需要很少的时间运行,却等待了很长时间。
SJF——Shortest Job First
算法思想:追求最少的平均等待时间,最少的平均周转时间、最少的平均平均带权周转时间
算法规则:最短的作业/进程优先得到服务(所谓“最短”,指要求服务时间最短)
用于作业/进程调度:
即可用于作业调度,也可用于进程调度。
用于进程调度时称为 “短进程优先(SPF,Shortest Process First)算法”;
是否可抢占: SJF和SPF是 非抢占式的 算法,但是 也有抢占式的版本—— 最短剩余时间优先 算法(SRTN,Shortest Remaining Time Next)
优缺点:
优点:“最短的” 平均等待时间、平均周转时间
缺点:不公平。 对短作业有利,对长作业不利。可能产生 饥饿现象。另外,作业/进程的运行时间是由用户提供的,并不一定真实,不一定能做到真正的短作业优先。
是否会导致 饥饿:会
如果源源不断的有短作业/进程到来,可能使长作业/进程长时间得不到服务,产生 “ 饥饿 ”现象。如果一直得不到服务,则称为 “ 饿死 ”
例:
非抢占式:
抢占式:
注意点:
HRRN——Highest Response Ratio Next
算法思想:要综合考虑作业/进程的等待时间和要求服务的时间
算法规则:在每次调度时先计算各个作业/进程的 响应比,选择 响应比最高的 作业/进程为其服务.
响 应 比 = 等 待 时 间 + 要 求 服 务 时 间 要 求 服 务 时 间 响应比 = \frac{等待时间+要求服务时间}{要求服务时间} 响应比=要求服务时间等待时间+要求服务时间
响应比 ≥ 1
用于作业/进程调度:即可用于作业调度,也可用于进程调度。
是否可抢占: 非抢占式的 算法,因此只有当前运行的作业/进程主动放弃处理机时,才需要调度,才需要计算响应比
优缺点:
优点:综合考虑了等待时间和运行时间(要求服务时间)
等待时间相同时,要求服务时间短的优先(SJF的优点)
要求服务时间相同时,等待时间长的优先(FCFS的优点)
对于长作业来说,随着等待时间越来越久,其响应比也会越来越大,从而避免了长作业饥饿的问题
是否会导致 饥饿:不会
例:
要动手算,算法特性容易考小题,算法的使用常结合调度算法的评价指标在大题中考察
RR——Round-Robin
算法思想:公平地、轮流地为各个进程服务,让每个进程在一定时间间隔内都可以得到响应
算法规则:按照各进程到达就绪队列的顺序,轮流让各个进程执行一个 时间片 (如100ms)。若进程未在一个时间片内执行完,则剥夺处理机,将进程重新放到就绪队列队尾重新排队
用于作业/进程调度:用于进程调度(只要作业放入内存建立了相应的进程后,才能被分配处理机时间片)
是否可抢占: 若进程未能在时间片内运行完,将被强行剥夺处理机使用权,因此时间片轮转调度算法属于 抢占式 的算法。由 时钟装置 发出 时钟中断 来通知 CPU 时间片已到
优缺点:
优点:公平,响应快,适用于 分时操作系统
缺点:由于高频率的进程切换,因此有一定开销;不区分任务的紧急程度
是否会导致 饥饿:不会
例:
时间片大小为2时:
时间片大小为5时:
和先来先服务调度算法对比:
可以看到当时间片大小为5时和先来先服务算法是一致的
1)如果 时间片太大,使得每个进程都可以在一个时间片内就完成,则时间片轮转调度算法 退化为先来先服务 调度算法,并且会 增大响应时间。因此 时间片不能太大。
2)进程调度、切换是有时间代价的(保存、恢复运行环境),因此如果 时间片太小,会导致 进程切换过于频繁,系统会花大量的时间来处理进程切换,从而导致实际用于进程执行的时间比例减少。可见, 时间片也不能太小。
算法思想:随着计算机的发展,特别是实时操作系统的出现,越来越多的应用场景需要根据任务的紧急程度来决定处理顺序
算法规则:调度时选择优先级最高的作业/进程
用于作业/进程调度:即可用于作业调度,也可用于进程调度。甚至,还会用于之后学习的 I/O 调度中
是否可抢占: 抢占式、非抢占式都有。
非抢占式:只需在进程主动放弃处理机时进行调度即可
抢占式:需要在就绪队列变化时,检查是否会发生抢占
优缺点:
优点:用优先级区分紧急程度、重要程度,适用于 实时操作系统。可灵活地调整对各种作业/进程的偏好程度
缺点:若源源不断地有高优先级进程到来,则可能导致饥饿
是否会导致 饥饿:会
例:
(优先级和优先数不是一个意思,注意题意进行区分,有的题可能优先数越小优先级越高)
非抢占式:
抢占式:
算法思想:对其他调度算法的折中权衡
算法规则:
1)设置多级就绪队列,各级队列优先级从高到低,时间片从小到大
2)新进程到达时先进入第1级队列,按FCFS原则排队等待被分配时间片,若用完时间片进程还未结束,则进程进入下一级队列队尾。如果此时已经是在最下级的队列,则重新放回该队列队尾
3)只有第 k 级队列为空时,才会为 k + 1 级对头的进程分配时间片
用于作业/进程调度:用于进程调度。
是否可抢占: 抢占式 的算法。
在k级队列的进程运行过程中,若更上级的队列(1~k-1级)中进入了一个新进程,则由于新进程处于优先级更高的队列中,因此新进程会抢占处理机,原来运行的进程放回k级队列队尾
优缺点:
优点:
对各类型进程相对公平(FCFS的优点);
每个新到达的进程都可以很快就得到响应(RR的优点);
短进程只用较少的时间就可完成(SPF的优点);
不必实现估计进程的运行时间(避免用户作假);
可灵活地调整对各类进程的偏好程度,比如CPU密集型进程、I/O密集型进程(拓展:可将因I/O而阻塞的进程重新放回原对了,这样I/O型进程就可以保持较高优先级)
缺点:可能导致饥饿
是否会导致 饥饿:会
例:
回顾:进程具有 异步性 的特征。异步性是指,各并发执行的进程以各自独立的、不可预知的速度向前推进。
操作系统提供 ” 进程同步 机制 “ 来实现 ” 预知 “ 需求
如:
另一个例子:
同步 亦称 直接制约关系,它是指完成某种任务而建立的两个或多个进程,这些进程因为需要在某些位置上 协调 它们的 工作次序 而产生的制约关系。进程间的直接制约关系就是源于它们之间的相互合作。
临界资源:
我们把 一个时间段内只允许一个进程使用 的资源称为 临界资源。
许多设备(如:摄像头、打印机)都属于临界资源,此外还有许多变量、数据、内存缓冲区等都属于临界资源。
对临界资源的访问,必须 互斥 地进行。互斥,亦称 间接制约关系。进程互斥 指当一个进程访问某临界资源时,另一个想要访问该临界资源的进程必须等待。当访问临界资源的进程访问结束,释放该资源后,另一个进程才能去访问临界资源。
对临界资源的互斥访问,可在逻辑上分为如下四部分:
为实现对临界资源的互斥访问,同时保证系统整体性能,需遵循:
1)空闲让进。临界区空闲时,可以允许一个请求进入临界区的进程立即进入临界区;
2)忙则等待。当已有进程进入临界区时,其他试图进图临界区的进程必须等待;
3)有限等待。对请求访问的进程,应保证能在有限时间内进入临界区(保证不会饥饿);
4)让权等待。当进程不能进入临界区时,应立即释放处理机,防止进程忙等待。
如果不互斥访问:
如何实现进程互斥:
若两进程并发运行,会产生问题:
可能会产生都在等待的情况:
Peterson 算法用软件方法解决了进程互斥问题,遵循了空闲让进、忙则等待、有限等待三个原则,但是依然 未遵循让权等待 的原则。
(因为进程进不了临界区,一直被卡在while循环中,一直还在CPU上执行,不断检查while循环的条件,会占用CPU资源,未满足让权等待原则)
Peterson 算法较前三种方案来说是最好的,但还不够好。
抓住 “谦让” 和 “表达意愿”
本小节常考
用户进程可以通过使用操作系统提供的 一对原语 来对 信号量 进行操作,从而很方便的实现了进程互斥、进程同步。
信号量:
其实就是一个变量 可以是一个整数,也可以是更复杂的记录型变量。
可以用一个信号量来 表示系统中某种资源的数量,比如:系统中只有一台打印机,就可设置一个初值为1的信号量。
注意 一个信号量对应一种资源
原语:
是一种特殊的程序段,其 执行只能一气呵成,不可被中断。原语是由 关中断/开中断指令 实现的。
软件解决方案的主要问题是由 “进入区的各种操作无法一气呵成”,因此如果能把进入区、退出区的操作都用 “原语” 实现,使这些操作能 “一气呵成” 就能避免问题。
一对原语:
如:
Tip:
单词联想记忆法:
(1)P对应单词pause,即暂停的意思,行动前先暂停检查下可用资源,等待(wait)到资源后即可行动;
(2)V对应单词,victory,行动胜利即凯旋卸甲(释放资源)
该记忆法源自网络
进程同步:
实现进程同步:
更复杂的同步问题:
消费者进程从缓冲区取出数据,若生产者进程处于阻塞态,消费者进程需将其唤醒,使生产者进程处于就绪态(生产者进程不会立即往缓冲区填数据)。
如果进程同时访问临界区,可能会出现问题,如两个生产者进程,可能会向同一块区域写入数据,造成数据覆盖,所以要互斥地访问。
生产和使用产品能否放到PV之间:
逻辑上是可以的。但是会使临界区代码变得更长,也就是说一个进程对临界区上锁的时间会变得更长,不利于各个进程交替的使用临界区资源,因此临界区代码要尽可能短。所以实际上不建议放在PV之间。
重要考点:
实现互斥的P操作要在实现同步的P操作之后,否则会导致死锁问题。
问题描述:
不同的生产者和消费者所生产和消费的东西是不一样的,多指 “多类”
问题分析:
1、关系分析:
2、整理思路:根据各进程操作流程确定P、V操作顺序
互斥:在临界区前后分别 PV;
同步:前 V 后 P。
3、设置信号量:
互斥信号量初值一般为1;
同步信号量初值要看对应资源的初始值是多少。
实现:
能否去掉互斥信号量?
即使不设置专门的互斥变量 mutex,也不会出现多个进程同时访问盘子的现象。
原因在于:此题缓冲区大小为1,在任何时刻,apple、orange、plate三个同步信号量中最多只有一个是1。因此在任何时刻,最多只有一个进程的P操作不会被阻塞,并顺利地进入临界区。
若将盘子容量改为2,即缓冲区大小为2:
重要考点:
从 “事件” 角度考虑:
问题描述:
生产者生产多种产品
问题分析:
1、分析关系:
2、整理思路
3、设置信号量
实现:
是否需要设置一个专门的互斥信号量?
不需要。缓冲区大小为1,同一时刻,四个同步信号量中至多有一个的值为1.
重要考点:
问题描述:
读者——读,写者——写
问题分析:
实现:
count 解决读者和读者之间可能不能同时访问的问题:
但是起初的 “加锁” 操作可能仍然会有两个读者 “同时” 进行,如 1进程 判断 count == 0 后,在进行 P(rw) 之前切换到 2进程,此时 2进程 同样可以 判断 count == 0 ,进行 P(rw) 操作使 rw = 0,等进程切回 1 时,1进程会被阻塞在 P 操作那。
多增加一个互斥信号量:
但是仍然存在 写进程饿死 的问题,再增加一个信号量:
重要考点:
问题描述:
问题分析:
实现:
每个哲学家吃饭前依次拿起左、右两支筷子
如何防止死锁发生?
或者:
即
重要考点:
引入管程的原因:
管程的定义
有点像 面向对象中的类
管程的基本特征
引入管程的目的是更方便地实现进程互斥和同步:
什么是死锁
在并发环境下,各进程因竞争资源而造成的一种 相互等待对方手里资源,导致各进程都阻塞,都无法向前推进 的现象,就是 “死锁” 。
发生死锁后,若无外力干涉,这些进程都将无法向前推进。
死锁、饥饿、死循环的区别
容易在选择中考察
死锁产生的必要条件
如果同类资源数> 1,则即使有循环等待,也未必发生死锁。(如上图所示)
如果系统中每类资源都只有一个,那循环等待就是死锁的充分必要条件了。
什么时候会发生死锁
死锁的处理策略
破坏互斥条件
破坏不剥夺条件
破坏请求和保持条件
破坏循环等待条件
银行家算法
本节重要
例:
Ⅰ、若B还想借30亿
此时借给B的30亿是不安全的…
Ⅱ、若A还想借20亿
如上答应A的请求,按 T -> B -> A 的顺序借钱是 OK 的;按 A -> T -> B 的顺序也 OK。
所以借给A的20亿是安全的…
安全序列
安全状态
如在上例 借给B 30亿后是不安全的,如果BAT没有提出再借20亿的请求,虽然系统处于不安全状态,但是还未发生死锁。(该点容易考察选择题)
因此可以在 资源分配之前预先判断这次分配是否会导致系统进入不安全状态,以此决定是否答应资源分配请求。(这也是 银行家算法 的核心思想)
1)资源总数(10,5,7),剩余可用资源(3,3,2)
将剩余可用资源与每个进程最多还需多少资源进行比对:
2)资源总数(10,5,7),剩余可用资源(5,3,2)
重新进行新一轮比对:
3)资源总数(10,5,7),剩余可用资源(7,4,3)
实际做题(手算)方法:
找不到安全序列的例子:
其中:
① 表示判断此次 i 申请的资源是否大于 i 所承诺的要申请的最大资源的数量;
② 表示判断系统中剩余的资源是否能满足此次 i 申请的资源;
③ 改变了三组数据,上例中执行第③步后修改如下:
检测:(例)
eg:
解除死锁的主要方法:
1、资源剥夺法
如何决定 “对谁动手”: