布吉做棋牌网站建设哪家服务好,河南郑州最新消息今天,如何做统计信息的网站,dedecms的网站放在哪个文件夹里文章目录 前言计算机系统概述OS的基本概念OS的发展历程OS的运行机制OS体系结构OS引导虚拟机 进程和线程进程和线程基础进程进程状态进程控制进程通信线程线程实现 CPU调度调度的层次进程调度细节调度算法评价指标批处理调度算法交互式调度方法 同步与互斥基本概念互斥互斥软件实… 文章目录 前言计算机系统概述OS的基本概念OS的发展历程OS的运行机制OS体系结构OS引导虚拟机 进程和线程进程和线程基础进程进程状态进程控制进程通信线程线程实现 CPU调度调度的层次进程调度细节调度算法评价指标批处理调度算法交互式调度方法 同步与互斥基本概念互斥互斥软件实现互斥硬件实现互斥锁自旋锁 信号量信号量机制信号量实现互斥同步 经典信号量问题生产者消费者——基本的分析思路多生产者多消费者——多种生产者吸烟者问题——多功能生产者哲学家进餐问题——连续申请多个资源读者写者问题——优先级互斥问题 管程 死锁死锁概述预防死锁——破坏死锁条件避免死锁——单步动态预测检测和解除死锁 前言
学校OS课程的知识和408有一定的重叠但是还不太够因此我又一次打开了王道的OS课程。
这个笔记同理只记最关键的内容和思考直接针对408基础性的概念性的知识以视频为主。
计算机系统概述
OS的基本概念 OS提供的服务
用户级别 GUI就是windows命令接口 联机有交互性即cmd命令行脱机批处理即.bat文件 程序员级别 系统调用OS的api系统调用可以通过c语言的操作系统库函数调用但是c语言本质上比系统调用还高一级 异步的前提是并发程序之间交叉前进即走走停停无法预知。
OS的发展历程 手工阶段缺点 独占人太慢机器速度逐渐加快人拖累机器 单通道批处理 优提升预处理速度不拖累机器缺独占 多通道批处理 优解决独占实现并发提升效率缺无交互能力 分时系统 优解决交互能力用户“看起来”独占缺没有优先级 实时系统 优解决了优先级响应问题及时可靠
OS的运行机制 OS内核相当于OS的管理员因此特权指令只能是内核执行。
平时用户的特权调用操作都是向管理员申请而不是亲力亲为。
两个状态的切换
升级特权指令触发中断硬件OS响应中断的时候进入核心态降级OS主动修改PSW让出控制权软件 修改PSW的指令本身就是特权指令 中断和计组第5章衔接
涉及到进程之间的协调就一定要OS接入进而需要系统调用。 需要注意陷入指令是用户态指令请求接下来才会因为内中断进入核心态执行 OS体系结构 我们OS学的功能可以放在内核也可以放在用户这就形成了大内核和微内核的区别。
微内核暴露的接口多易于维护和扩展但是沟通成本大要反复调用。 分层结构 类似于计网的层次结构结构清晰通病是效率偏低 模块化 主模块分离模块之间分离平等 优点可以同时开发且效率不错缺点模块间的图关系很难把握 动态可加载模块。 可加载说白了就是插件有没有都不影响运行因此可以动态加载比如驱动 宏内核和微内核 微内核相当于一个服务器中转不同模块之间的消息传递 外核 外核可以提供一些高级的资源未经抽象的资源分配方式内核分配的资源都是抽象的虚拟化的比如虚拟地址外核可以直接分配物理地址在一些需要频繁跳跃的场景外核直接分配一片连续空间效果会很好。当然外核也负责保证安全。跳过虚拟步骤就相当于跳过了映射层可以提高效率缺点是复杂。
OS引导 简单来说就是开机扫ROM就可以把操作系统拉起来但是具体还是要分几步走
扫ROM启动BIOS自检读磁盘的MBR获取分区从活动分区C盘中读PBR获取C盘根目录通过目录找到操作系统的程序拉到内存中完成OS启动
这四步环环相扣前一个获取了信息后一步才能根据此信息行动。
而第4步用的程序位置一般在C:/Windows/Boot/下面。
虚拟机 第一类VMM相当于传统OS的加强版直接运行在硬件上 虚拟OS看起来像一个OS也有内核但是实际上还是用户态因此一个特权指令实际上要经过一次虚拟的系统调用一次真正的系统调用。迁移性差因为直接和硬件耦合 第二类VMM是寄居在宿主OS之上的分为两部分 用户态的VMM和宿主的应用程序是共存的核心态的VMM是以驱动的形式存在的持续运行在内核态 进程和线程
进程和线程基础
进程 PCB记录进程元数据
描述信息。用于区分进程PIDUID进程控制和管理信息。和进程运行状态有关资源分配清单。 资源是进程外部的而数据段是程序产生的内部数据 处理器相关信息。寄存器上下文
进程特征
并发性和异步是一起的结构性指的是每个进程的结构都一样都是PCB数据段程序段
进程状态 进程控制 创建原语分为4步
PCB创建和初始化分配资源此时进入就绪态插入就绪队列
撤销是逆过程
剥夺所有资源清理子进程删除PCB 阻塞和唤醒是可逆的过程
修改PCB可逆所以现场要保护起来切换队列把PCB放到对应队列中
无论是阻塞还是进程切换都要剥夺CPU而进程有一些内容还存在寄存器中这些寄存器上下文就是保护现场要做的工作是中断隐指令的内容。 进程通信 共享储存 把两个进程的虚拟储存映射到同一个物理储存区域因此要互斥访问 消息传递 每一个进程都有一个消息队列直接通信A进程把消息直接挂到B进程消息队列里间接通信以信箱为中介B要主动去信箱取出A发来的消息 管道通信 联系生产者消费者管道其实就是一个循环队列是个内存缓冲区管道互斥访问因此是半双工像水管
线程 TCBThread CB一个进程内部线程之间资源共享 因此切换成本很小其就是为了频繁切换提高并发性而生的。 一个程序的多线程可以放到不同进程中 多核CPU的超线程但是这样就无法共享资源了各用个的 线程可以理解为剥离掉公用资源后剩下的相互独立的部分
因此线程的内容比较少切换的时候只需要保证TCB里面的一些寄存器上下文就可以比进程少很多。
线程实现 用户级线程适用于早期OS没有线程管理功能的时候
本质上是用户自己用代码线程库管理线程的调度 在OS看来只有一个进程而已线程的调度是纯用户态行为这种调度非常简单线程库的逻辑 优缺点 优不需要系统调用高效缺假线程代码在一个线程卡住实际上都卡住了 内核级线程这是经典的OS负责的线程
优点真并发缺点核心压力大
因此内核级线程又分出多种模式
一对一 这其实和内核级线程一样 多对一多个用户级线程对应一个内核线程而CPU只能看到内核线程 这个模式比较鸡肋和用户级线程一样 多对多多个用户级线程映射到多个内核线程 这才是真神可以把用户线程切分成3块每一块都用多对一模型映射到一个线程整体上三个部分有序工作互相之间不会拖累兼顾了效率和并发性 CPU调度
调度的层次 作业调度作业≈一个程序储存的位置是外存作业调度≈程序启动 低级调度针对进程切换CPU
中级调度和作业调度一样都是在内外存之间的区别如下
作业调度是比较彻底就是启动和终止中级调度类似于休眠挂起暂时放到外存手机的扩展内存技术就是这样实现的 引入7状态模型对就绪和阻塞分别增加对应的挂起状态在挂起状态外存里也可以实现阻塞到就绪的转变从运行态可以跳过就绪态直接跳到挂起 进程调度细节 进程调度时机
主动被动。说白了就是被抢占 中断处理中断隐指令和原子操作都会关中断因此不会被打断OS内核处理内核临界区的时候权限高不可被打断
区分一下
狭义进程调度。在CPU空闲的时候抓一个就绪态进程激活进程切换。剥夺一个运行的进程换成另外一个进程 两个操作都要恢复新现场相比于调度切换额外要做的操作是保护旧现场
广义的进程调度可能包含了进程切换这一过程 最后提一嘴调度程序我们说调度是由OS控制的本质上就是软件那么说白了负责调度的管理者还是一个程序。
这个程序什么时候会运行呢
如果是非抢占的时候就是异步的运行在特殊情况才运行创销阻塞唤醒抢占式的那么就要定期巡查决定一个CPU是否应该抢占
调度算法
评价指标 周转时间等待处理时间带权周转时间 本质上是个比例值可以衡量等待时间在周转时间中的占比越大则等待越久 等待时间。 执行之前的时间执行起来后等IO的时间不算作业的等待时间是在成为进程之前的那段时间进程的等待时间就是创建态就绪态的那段时间 响应时间 和等待时间类似但是针对的只是一种请求比如键盘鼠标
批处理调度算法 对于非纯计算程序IO时间不算等待因此还要抛去IO操作的部分。
FCFS其实就是FIFO之所以对短作业不利就是因为短作业的带权周转时间会很大这代表其体验很差。 短Short即SJFSPF
具体计算要分为三部分
还没来的作业作业池中的作业正在运行的作业
正在运行的作业只能在作业池中挑选而不能是还没有进入作业池的因此第一个任务只能是P1即使他时间很长。
SJF分两种
非抢占式的SJF如上 比较简单顺序操作只需要在作业完成时分析作业池即可 抢占式的SJFSRTN 如果有一个新的作业来了那么就有可能比当前正在运行的作业的剩余时间短此时就把作业替换回作业池中记得标注剩余时间具体做题的时候比非抢占式要额外多分析新作业来的时间点 题目区分细节 默认非抢占但是比较模糊考虑到抢占SRTN的平均周转时间肯定是最少的如果默认作业没有到达顺序的先后之分那么非抢占SJFSRTN SJF对长作业不利无论是否抢占都可能造成饥饿现象 HRRN用到响应比指标综合了等待时间和处理时间在保证了优先级的前提下修复了SJF饥饿的问题。
分析思路和SJF类似都是分成三部分HRRN为非抢占式的所以只在CPU空闲的时候对作业池进行分析。
注意其等待时间是从到达开始计数的。
交互式调度方法 RR时间片轮转
轮转本身很简单 建立一个就绪队列每一个时间片出队处理队头对应的进程时间片完了以后就插到队尾 难在新任务来的时候会改变队列结构 新任务来了也是插在队尾如果A任务的时间片完了此时B任务刚来这二者的顺序以B为先毕竟新来的要照顾一下注意这个照顾顺序只针对想要同时入队的两个任务前面早就在队里的任务仍然在前面 如果任务处理完时间片还没用完会直接终止当前时间片 很正常很人性化的设计干等着没意思
因此整个分析过程需要考虑的也是处理完以及新任务刚来的两种时刻。
严格来说RR不会剥夺正在执行的时间片但是先来先插到队尾的这种逻辑以及规定时间片用完就剥夺这两个操作具有抢占性所以我们规定RR是抢占式的剥夺的来源是时间片本身而不是其他进程
时间片太大就会退化为FCFS太小则切换开销占时间片的比例就太大了类似于流水线那个感觉效率降低。 优先级调度算法。优先数越高就越排在前面激活。
此方法分为抢占式和非抢占式。 分析节点参考SJF。 多级反馈队列调度这个是666真神
我们直接分析一下其性质相当复杂但是又相当合理
队列内部是RR队列之间是抢占关于优先级 新手保护刚来的优先级最高耗时降级如果耗时长每完整执行一个时间片优先级就会降低一级直到降无可降被剥夺不降级被剥夺严格来说不算执行完一个时间片因此不降级只是按RR原则放到了队尾。不过还会有补偿新获得的时间片又是一个完整的时间片 关于轮转 优先高级高一级的队列为空才对下一级进行RR遍历有抢占性如果高一级来了新的则立马切到高一级保障低级越低级时间片越长。虽然低优先级低人一等但是总得让人家执行完所以低优先级的时间片反而会更多一旦轮到了就可以持续执行很长时间当然如果你不争气执行不完那就继续降级又或者被强占总之还是低人一等
优缺点分析
公平FCFS快响应RR优先级调度短进程优先SPF自动优先级 如果想要保证任务的高优先级可以尽量让其不降级比如如果进程因为IO主动放弃时间片此时我们不认为其执行完毕因此不降级这样就保证了IO的高优先级 缺点仍然不是绝对公平因此会造成饥饿
在具体实践中为了防止饥饿出现可能一个队列会分配固定的时间上限如果超过这个界限还是要切换队列的不能一直卡在高优先级队列。 此外不同队列内部的策略还可以不一样。 同步与互斥
基本概念 异步就是无序性 同步就是有序性A一定在B前。
遵循的原则总结起来就是忙可以先等一下等久了就撤让权但是你不能让我等太久过一段时间我还得拿回权利并且进入临界区。
互斥
互斥软件实现 单标志法是最原始的轮询
本质上turn代表谦让以及指定刚开始就指定一个进程而一个进程执行完以后又会指定另外一个进程。 但是其问题在于临界区使用权和CPU占用权是分裂的让给你用并不代表你就能用即空闲也进不去违背“空闲让进”
比如此时标记0进程能用临界区但是此时CPU时间片属于1此时while循环就会持续1个时间片一边是忙等另一边是空闲没人用 双标志法把谦让逻辑变成了将指定变成了排他逻辑占用逻辑。
占用和释放只修改自己的占用标记不去指定他人。
双标志先检查检查和上锁不连贯此时按照1526顺序A还没上锁B就通过检查了就会同时进入临界区即“忙”也能进去违反了忙则等待。
为了修正出现了双标志后检查法这种方法先把临界区标记了再检查那么就可以确保别人拿不到临界区缺德做法但是这很明显不靠谱会出现都用不上的情况按照1526顺序AB都标记则会排他那么AB就都会卡在检查阶段。
此时即使临界区空闲AB谁也不让着谁谁也用不上这违背了“空闲让进”而且一直卡死违背了“有限等待” peterson算法综合了单标志和双标志后检查法
标志代表意愿turn代表谦让最后被谦让的那一个就可以获得使用权。
以1627举例2先谦让一下但是7后面有谦让一下于是2就勉为其难的进入了和现实的套路一模一样。 本质上turn同一时间有且只能有一个值因此同一时间只能有一个进程跳出循环且必有一个进程跳出循环。
非常牛逼的思路但是仍然优缺点因为进程仍然是忙等状态即违反了“让权等待”但是已经是成本最低的了这个操作可以通过时间片轮转来剥夺。
互斥硬件实现 关中断的缺点
多处理机关不了其他CPU进程可以借助其他CPU访问临界仅内核。因为这个操作给用户太危险 TestSet的操作说白了就是用old检查并对lock进行上锁这是一个原子过程检查和上锁是一气呵成的。 如果lock原来就是true那么再上也无所谓 如果lock原来是false那么就可以同时实现上锁退出循环不用担心被打断
上面这个代码只是模拟实际上是硬件TSL指令实现的是原子的而软件编程是无法达到这个效果的。 缺点和peterson一样都是忙等不满足“让权等待”原则
还有一个Swap指令ExchangeXCHG指令和TSL基本一样的逻辑和特性
互斥锁自旋锁
互斥锁是一种思想和mutex操作很像就是申请和释放。
但是其申请过程是忙等的所以TSLswap指令都是自旋锁单标指法其实也是自旋锁申请过程都具有原子性
当然正如单标志法哪里说的忙等其实不完全忙等时间片没了就退出单处理器没有RR所以就是彻底忙等。甚至说有时候反而有意外效果等待的时候不用切换上下文有时候成本反而低。 信号量
信号量机制 整形信号量说白了就是双标志先检查但是P和V是原语可以保证不会同时进入
但是因为底层还是一个循环仍然会忙等不满足让权等待。 记录型信号量引入阻塞队列解决了忙等现象
原来是忙等现在发现资源不够就丢到阻塞队列里。 极限情况为0-1后为负此时是第一个进程阻塞 如果资源够了且阻塞队列里有进程就唤醒 极限情况为-11后为0此时把阻塞队列里最后一个进程唤醒
信号量实现互斥同步 semaphore mutex 1 代表记录型信号量有等待队列
互斥比较简单mutex1PV夹住临界区。 同步是前V后P用一个信号量关联两个进程等V操作执行完后P才能执行下去。
给定一个拓扑图只需要把每一个前驱后继关系都用一个信号量定义一下即可。 之后每一个节点都是一个进程把边定义的前驱后继关系写到进程里面即可
入边写P出边写V 经典信号量问题
生产者消费者——基本的分析思路 需要注意一个细节就是P操作是不可互换的因为mutex只夹临界区夹得多了就会出问题死锁 V操作可以互换因为V操作一定不会被卡住 多生产者多消费者——多种生产者 首先是最简单的两组关系
apple和orange各自有一对同步关系plate关系关键在于盘子盘子是双方的一个中介并不能单看父或者母要把父母统一为一方把子女统一为另一方
具体实现如下三个同步信号量这里将plate设置为“还可以放的空间”因此初值为1
因此整体就实现了一个PV结构每一个进程都是有P有V。 mutex实际上可有可无因为我们这里的资源上限为1已经相当于mutex的作用了但是如果盘子空间变成2就得加mutex了否则就可能发生覆盖现象。 如果反过来呢plate盘中可用水果数量会出问题比如dad此时就是VappleVplate可以看到这个进程是没有P的也就是说不会被阻塞他可以一直释放。
所以我们这里还可以总结出一条生产者消费者问题中隐性的要求就是PV一定是要成环的相互制约一个进程只有V无P必然是有问题的在我们制定信号量意义的时候也应该考虑构造一个PV环结构。
吸烟者问题——多功能生产者 一个多功能生产者给多个单功能消费者提供原料同步关系如下 再拓展一下思路如果finish定义为1呢
那么就要把生产者的P操作放在最开始消费者是不变的仍然可以正常运行因为仍然是PV环而且PV关系没有变
分析一下是否需要mutex因为只有一个生产者所以缓冲区最多有1个元素不会出问题。 但是呢如果有n生产者此时因为生产者是V在前的第一次生产不受阻塞所以就可能会让缓冲区里存在n个元素所以这种写法其实不好如果是按照我那个P在前的写法即使是有多个生产者进程只要规定finish1就只能有一个元素被生产
哲学家进餐问题——连续申请多个资源
这个问题本身不难难在如何解决死锁。
哲学家进餐问题的死锁情况为每个哲学家都只P了一半都卡在了第二个P上。 本质上哲学家进餐是连续申请多个资源如果申请的途中被卡了而且是集体卡顿那就死锁了。
所以解决哲学家死锁就要从这些领域入手
最多让n-1个哲学家同时进餐这样就一定可以保证有1个哲学家不会被卡死 可以用一个值为n-1的信号量限制 限定哲学家拿资源的顺序强制哲学家进行两两竞争 比如指定奇数哲学家先左边的偶数先拿右边的那么这一对哲学家必然是两个必有一个阻塞而另一个没被阻塞的哲学家在另一边不存在竞争一定可以吃到 保证哲学家多个P操作的原子性 在一连串P外面加个mutex即可即使一个哲学家被卡其他哲学家也不可能是P操作被卡即其他哲学家在吃饭这是暂时的可以恢复的 读者写者问题——优先级互斥问题 代码分为4个版本
单进程读/写全部互斥读者优先读写公平写者优先
这四个版本2实现了多读者同读234逐步提高写者的优先级具体的思想如下
插队逻辑通过if语句可以制造插队提高优先级 副作用是多进程可以同读同写读者优先利用了这个副作用其本意只是提高优先级顺带实现同读 抵消插队逻辑在保留插队逻辑副作用同读的基础上抵消插队带来的优先级效果 在插队逻辑外面加一个信号量即可设为w注意对w而言高优先级的进程w是覆盖所有代码的低优先级的进程w仅覆盖进入区以及插队逻辑由此w提高优先级和插队逻辑的优先级效果就互相抵消了这种思路必须要基于插队逻辑才行因为w并不是针对临界区的管控至少还得有一个信号量rw管控临界区 控制同时读/写在插队逻辑的前提下选择性的控制是否可以同读同写 读者优先中直接对临界区信号量rw加插队逻辑利用了插队的副作用无伤实现同读写者优先不可以这么做所以需要把插队逻辑外提到非临界区信号量w即使可以插队新来的也得一起卡在临界区外面 这是最基础的读者优先结构这个结构务必理解透彻了。
rw直接对临界区上锁副作用是会造成读读互斥插队逻辑消除读读互斥并提升r的优先级 if判断现在加了判断使得读者里面只有第一个和最后一个读者需要维护锁其他情况下只要有读者在读新来的就可以直接读mutex令count判断部分原子化保护count变量 读写公平如上是在读者优先的前提下修改的仍然保证了读者不互斥的特性 但是使用信号量w额外增加了读者对写者的反制能力说白了就是用w抵消了读者的插队能力。
这个w加的位置非常巧妙
对于写者来说w是覆盖了临界区的也就是说可以造成写者互斥的效果对于读者来说w只是卡在了最开始的进入区这样就不会造成读者互斥w和rw使得读者和写者可以相互钳制 读者在进入区则写者卡在w读者在临界区获取rw释放w则写者可以进一步卡在rw已经获取了w写者在进入区获取w卡在rw其余读者/写者已经进不了进入区了卡在w写者在临界区同写者在进入区
如果要实现写者优先呢 还是插队逻辑在读写公平的前提下给写者增加一个插队逻辑
为了防止出现同写情况需要将插队逻辑外提到w上。
不能像读者那样插。读者是可以共同读的写者不行所以不能给rw加插队逻辑考虑给w加插队逻辑这样写者可以源源不断的到达“进入区” 实际上这个操作就是修改了读写公平里的这句描述其余读者/写者已经进不了进入区了卡在w给写者开了个后门 为什么不能像读优先那样直接照搬写一个写优先 因为读优先是可以同读的但是写无法同写所以要外提插队逻辑所以一定是不能照搬的写优先还可以爆改一下反正都写优先了把读的插队逻辑去掉也是可以的当然这样就不能同读了
semaphore rw1; //读写公用临界区信号量
int rcount0; //读者插队逻辑
semaphore rmutex1;semaphore w1; //用于提升write的优先级
int wcount0; //写者插队逻辑
semaphore wmutex1;reader(){while(1){P(w);//抵消插队逻辑优先级P(rmutex);//保护rcountif(rcount0)//插队逻辑P(rw);rcount;V(rmutex);V(w);//注意抵消插队逻辑优先级的时候被抵消方的Vw插在临界区前写文件//临界区P(rmutex);rcount--;if(rcount0)V(rw);V(rmutex);}
}writer(){while(1){P(wmutex);if(wcount0)//w对写者加入插队逻辑P(w);wcount;V(wmutex);P(rw);//公用临界区信号量读文件//临界区V(rw);P(wmutex);wcount--;if(wcount0)V(w);V(wmutex);}
}代码分为4个版本
单进程读/写全部互斥读者优先读写公平写者优先
这四个版本2实现了多读者同读234逐步提高写者的优先级具体的思想如下
插队逻辑通过if语句可以制造插队提高优先级 副作用是多进程可以同读同写读者优先利用了这个副作用其本意只是提高优先级顺带实现同读 抵消插队逻辑在保留插队逻辑副作用同读的基础上抵消插队带来的优先级效果 在插队逻辑外面加一个信号量即可设为w注意对w而言高优先级的进程w是覆盖所有代码的低优先级的进程w仅覆盖进入区以及插队逻辑由此w提高优先级和插队逻辑的优先级效果就互相抵消了这种思路必须要基于插队逻辑才行因为w并不是针对临界区的管控至少还得有一个信号量rw管控临界区 控制同时读/写在插队逻辑的前提下通过控制插队的信号量选择性的控制是否可以同读同写 如果把插队逻辑加在临界区信号量上就会造成同读/写外提则不会读者优先中直接对临界区信号量rw加插队逻辑利用了插队的副作用无伤实现同读写者优先不可以这么做所以需要把插队逻辑外提到非临界区信号量w即使可以插队新来的也得一起卡在临界区外面
管程
PV操作和生产消费过程混在一起耦合度高容易出错
因此直接把控制互斥同步的部分剥离出来封装成类管程
在管程内部定义变量和初始化在管程内部定义方法实现同步机制至于mutex互斥管程通过方法的互斥来实现同一时间只能有一个进程调用管程 编译器会自动实现也就是说你只需要定义同步就可以 死锁
死锁概述 死锁的条件
前提是争抢互斥其次是占着不放不剥夺不仅不放还要持续地请求别的资源请求和保持条件 换句话说就是在只获取了部分资源的前提下还要获取更多资源 满足这三个大前提一旦成环循环等待条件则死锁
预防死锁——破坏死锁条件 破坏互斥。这个思路看着就不靠谱破坏不剥夺。进程要反复切换开销大而且持续剥夺会导致饥饿 方案一主动退位方案二OS协助剥夺 破坏保持和请求。 保持和请求本质上是因为只获取了一部分资源不得不继续请求剩余资源那么我们干脆一次性给到位再让他启动否则就干脆不给没有中间态。很显然利用率低饥饿 破坏循环等待。 给资源编号规定一个进程申请资源的编号是递增的众多进程中必然有一个进程掌握已有的最大编号的资源比如下图的7号资源这个进程需要的资源编号肯定比在场所有进程资源的编号都大至少是8也就是说这个大编号进程要的资源只可能是空闲的即使其他进程卡死这个进程一定也可以执行下去很显然不方便浪费
避免死锁——单步动态预测
看下来可以发现死锁预防的方法缺陷都很大。
银行家算法是一个动态预测的方法其实和前面那个破坏保持和请求条件的思路类似保证资源够用具体做法如下
每次分配之前我都要确保分配之后仍然是安全状态。 所谓的安全状态就是分配了以后我仍然有足够的资源让一个进程彻底执行完毕 这是做最坏的打算只要我每一次分配都是在安全状态上那就确保不会发生死锁。这是一种非常保守的思路。
当然有的情况是最保守的策略都无法解决的那就死锁是必然的要从其他地方找问题如下图 检测和解除死锁 上面介绍的预防和避免都比较简单死锁检测通过软件的思路设计算法去对图结构进行分析可以得到好的全局分析结果。 给定一个资源分配图图中有4类元素注意点如下
资源里面的点数代表资源最大出度 点数-资源已有出度可用资源数量 进程的出度代表申请的资源数
具体做的时候就是找出能够先执行完的进程执行完将资源释放然后滚雪球化简资源分配图直到所有进程执行完毕。
能够先执行完的进程怎么找呢就是去计算一下可用资源数量是否满足进程申请的资源数 以上图举例P1申请1个资源R2剩2-11个资源所以P1可以执行下去之后逐步化简就好
如果化简不完最后有剩余的一个环那么就代表这些进程构成了死锁循环针对性的剥夺就好了。 这就是软件全局分析的好处精准。
解除死锁的方法辨析
资源剥夺法。 单纯剥夺资源进程只是挂起歇一会这样可能导致饥饿 撤销进程法 直接remake死锁进程啥都没了可能造成浪费白干了 进程回退法 类似于git的回滚回到一个可以完全消除所有边的状态这个理想很好实际上很难实现因为要记录回退点
至于对哪个进程动手归根结底就是对优先级低的动手让出机会给高优先级任务。