星星博客 »  > 

操作系统基础知识1

一、操作系统(2019王道考研)

二、 操作系统的特征

并发、共享、虚拟、异步,其中前两个为最基本的特征。

并发: 指两个或多个事件在同一时间间隔内发生。(宏观上是同时发生的,微观上是交替发生的)
并行: 指两个或多个事件在同一时刻同时发生。

共享: 即资源共享,是指系统中的资源可供内存中多个并发执行的进程同时使用。

  1. 互斥共享方式:系统中的某些资源,虽然可以提供给多个进程使用,但是同一时间段内只允许一个进程访问该资源。
  2. 同时共享方式:系统中的某些资源,允许一个时间段内由多个进程“同时”对它们进行访问。(宏观上同时,微观上可能是交替的进行资源的访问,即分时共享)

虚拟: 是指把一个物理上的实体变为逻辑上的对应物,分为空分复用技术(虚拟存储器技术)和时分复用技术(虚拟处理器)

异步: 是指在多道程序环境下,允许多个程序并发执行,但是由于资源有限,进程的执行不是一贯到底的,而是走走停停,以不可预知的速度向前推进,这就是程序的异步性。

三、 操作系统的发展和分类

在这里插入图片描述

四、 操作系统的运行机制与体系

在这里插入图片描述

指令:处理器(CPU)能识别、执行的最基本命令,比如加法指令就是让CPU进行加法运算。

两种指令、两种处理器状态、两种程序

  1. 特权指令:如内存清零指令,不允许用户程序使用;
  2. 非特权指令:如普通的运算指令

那么cpu是如何判断当前是否可以执行特权指令?根据不同的处理器状态,这个用户状态字寄存器(PSW)中的某标志位来标识当前处理器处于什么状态。如0是用户态,1是核心态。

  1. 用户态(目态):此时CPU只能执行非特权指令;

  2. 核心态(管态):特权指令,非特权指令都可执行(陷入指令是惟一一个只能在用户态执行不能在核心态执行的指令,陷入指令的作用是引发一个内中断,使CPU进入核心态);

  3. 内核程序:操作系统的内核程序是系统的管理者,既可以执行特权指令,也可以执行非特权指令,运行在核心态;

  4. 应用程序:为了保证系统能安全运行,普通应用程序只能执行非特权指令,运行在用户态。

问题:操作系统中的哪些功能应该由内核程序实现呢?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、中断和异常

在这里插入图片描述
早期的计算机只能串行执行,系统资源的利用率低,为了解决这个问题,操作系统中引入了中断机制,实现了多道程序并发执行。

本质:发生中断就意味着操作系统介入,开展管理工作。

CPU收到计时部件发出的中断信号,切换为核心态,对中断进行处理

在这里插入图片描述
中断分为内中断(信号来源 为CPU内部)和外中断(信号来源 为CPU外部)
在这里插入图片描述
还有另外一种分类方式:
在这里插入图片描述
在这里插入图片描述

六、系统调用

6.1 什么是系统调用,有何作用?

操作系统作为用户和计算机硬件之间的接口,需要向上提供一些简单易用的服务。主要包括命令接口和程序接口。

  • 命令接口:是允许用户直接使用。
  • 程序接口:允许用户通过程序间接使用–>有一组系统调用组成

系统调用的作用:
在这里插入图片描述

6.2 系统调用背后的过程?

在这里插入图片描述
在这里插入图片描述

系统调用时操作系统向上提供的接口,当今编写的应用程序大多是通过高级语言提供的库函数间接的进行系统调用。

七、进程

7.1 进程的组成

内存中同时放入多道程序,各个程序的代码、运算数据存放的位置不同,操作系统要怎么才能找到各程序的存放位置?

系统为每个运行的程序配置一个数据结构,称为 进程控制块(PCB) ,用来描述进行的各种信息(如程序代码存放位置)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.2 进程的组织

在这里插入图片描述

7.3 进程的特征

在这里插入图片描述

7.4 进程的状态和转换

进程的三种基本状态:运行态、就绪态、阻塞态
在这里插入图片描述
除了三种基本状态,还有另外两种状态–创建态和终止态
在这里插入图片描述

进程状态的转换
进程创建后在初始化的过程中处于创建态,如果系统完成了创建进程的一系列工作之后,进程就进入到就绪态(也就是拥有了处理机之外的其他资源),处于就绪态的进程被调度就进入到运行态,被处理机处理。

如果处于运行态的进程时间片用完了,或者处理机被优先级更高的进程抢占,那么这个进程就会从运行态重新回到就绪态。
如果处于运行态的进程用“系统调用”的方式申请某种系统资源,或者请求等待某个事件发生,就会进入阻塞态(处理机资源被剥夺,并且所需的其他资源也没有就位)。

当处于阻塞态的进程申请的资源被分配,或者等待的时间发生,就会重新进入就绪态。

如果处于运行态的进程运行结束,或者运行过程中遇到了不可修复的错误,那么会进入终止态,由操作系统完成一系列后续工作。
在这里插入图片描述
本部分总结
在这里插入图片描述

7.5 进程控制

7.5.1 什么是进程控制

进程控制的主要功能是对系统中的所有进程实施有效的管理,它具有创建新进程、撤销已有进程、实现进程状态转换等功能。简单来说,就是实现进程状态转换。

7.5.2 如何实现进程控制

在进程状态转换的过程中,需要不断的根据进程的状态修改PCB的内容,并且将进程加入到相应的队列,但是如果进程的状态与队列不匹配,则会出现问题,为了防止这种问题,所以用 原语 实现进程控制。
在这里插入图片描述
原语的特点是执行期间不允许中断,只能一气呵成。

原语采用“关中断指令” 和 “开中断指令”实现。(只允许在核心态下执行的特权指令)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.6 进程通信

进程通信就是指进程之间的信息交换。

进程是分配系统资源的单位(包括内存地址空间),因此各进程拥有的内存地址空间相互独立。

为了保证进程的安全,一个进程不能直接访问另一个进程的地址空间,但是进程之间的信息交换又是必须实现的,为了保证进程间的安全通信,操作系统提供了一些方法:共享存储、消息传递、管道通信

7.6.1 共享存储

两个进程对共享空间的访问必须是互斥的(互斥访问通过操作系统提供的工具实现,比如P、V)。
在这里插入图片描述

7.6.2 管道通信

“管道”是指用于连接读写进程的一个共享文件,又名pipe文件。其实就是在内存中开辟一个大小固定的缓冲区。

注意:

  1. 管道只能采用半双工通信,某一时间段只能实现单向的传输,如果要实现双向同时通信,则需要设置两个管道;
  2. 各进程要互斥地访问管道;
  3. 数据以字节流的形式写入管道,当管道写满时,写进程的write()系统调用将被阻塞,等待读进程将数据取走。当当读进程将数据全部取走后,管道**变空,**此时读进程的read()系统调用将被阻塞。
  4. 如果没写满,就不允许读,如果没读空,就不允许写
  5. 数据一旦被读出,就从管道中被抛弃,这就意味着读进程最多只能有一个,否则可能会有读错数据的情况。

7.6.3 消息传递

进程间的数据交换以格式化的消息(Message)为单位。进程通过操作系统提供的“发送消息/接收消息”两个原语进行数据交换。

在这里插入图片描述
本部分总结
在这里插入图片描述

7.7 线程、多线程模型

7.7.1 什么是线程,为什么要引入线程?

有的进程需要同时做很多事,而传统的进程只能串行地执行一系列程序。为此,引入了“线程”,来增加并发度。

线程是一个基本的CPU执行单元,也是程序执行流的最小单位,引入线程之后,不仅是进程之间可以并发,进程内的各线程之间也可以并发,从而进一步替代哼了系统的并发度。

引入了线程之后,进程只作为除CPU之外的系统资源的分配单元。
在这里插入图片描述

7.7.2 线程的属性

在这里插入图片描述

7.7.3 线程的实现方式

在这里插入图片描述
在这里插入图片描述

在同时支持用户级线程和内核级线程的系统中,可采用二者组合的方式:将n个用户线程映射到m个内核级线程上(n>=m)

重点:操作系统只“看得见”内核级线程,因此只有内核级线程才是处理机分配的单位。
上面那张图将三个用户级线程映射到两个内核级线程上,所以即使该进程运行在一个四核处理机的计算机上,也最多只能被分配到两个核,最多只能有两个用户线程并行执行。

7.7.4 多线程模型

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
本部分总结
在这里插入图片描述

7.8 处理机调度

7.8.1 调度的基本概念

当有一堆任务要处理,但由于资源有限,这些事情没法同时处理,这就需要确定某种规则来决定处理这些任务的顺序,这就是“调度”研究的问题。

处理机调度就是从就绪队列中按照一定的算法选择一个进程并将处理机分配给它运行,以实现进程的并发执行。

7.8.2 调度的三个层次

在这里插入图片描述
在这里插入图片描述

提到挂起,这里可以补充一下进程的挂起态和七状态模型:
在这里插入图片描述
在这里插入图片描述

7.8.3 三个层次的联系、对比

在这里插入图片描述
本部分总结
在这里插入图片描述

7.9 进程调度的时机、切换与过程、方式

7.9.1 进程调度的时机

在这里插入图片描述

下面详细解释下第二条:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在访问内核程序临界区的时候不能进行进程的切换,但是在访问普通临界资源的时候是可以进行进程的切换,比如打印机。

7.9.2 进程调度的方式

在这里插入图片描述

7.9.3 进程的切换与过程

在这里插入图片描述
本部分总结
在这里插入图片描述

7.10 调度算法的评价指标(理解会计算)

7.10.1 CPU利用率

利用率 = 忙碌的时间/总时间

7.10.2 系统吞吐量

单位时间内完成的作业数量。

系统吞吐量 = 总共完成了多少作业/总共花了多少时间

7.10.3 周转时间

指作业被提交给系统开始,到作业完成为止的时间间隔。

周转时间 = 作业完成时间 - 作业提交时间

平均周转时间 = 各作业周转时间之和/作业数

带权周转时间 = 作业周转时间/作业实际运行的时间

平均带权周转时间 = 各作业带权周转时间之和/作业数

带权周转时间必然>=1, 并且带权周转时间和周转时间都是越小越好。
带权周转时间其实就是看转转时间为作业时间运行时间的多少倍,该值越大用户体验越差!

7.10.4 等待时间

等待时间,是指进程/作业等待处理机状态时间之和,等待时间越长,用户满意度越低。

进程:等待时间是指,进程建立建立后等到被服务的时间之和。(周转时间-运行时间-运行中等待其他资源的时间)
作业:等待时间是指进程等待时间+作业在外存后备队列中等待时间。

注意: 等待I/O设备的时间不算是等待时间!

7.10.5 响应时间

从用户提交请求到首次产生响应所用的时间。

本部分总结
在这里插入图片描述

7.11 调度算法

学习的思路:

  1. 算法的思想
  2. 算法的规则
  3. 这种调度算法是用于作业调度还是进程调度?有什么区别?
  4. 抢占式?非抢占式?
  5. 缺点和优点
  6. 是否会导饥饿(某进程或作业长期得不到服务)

7.11.1 先来先服务(FCFS)

在这里插入图片描述

7.11.2 短作业优先(SJF,Shortest Job First)

在这里插入图片描述

从上面的分析可以看出,先来先服务算法在每次调度的时候选择一个等待时间最长的作业(进程)为其服务,但是没有考虑到作业的运行时间,因此导致了对短作业不友好;SJF算法是选择一个执行时间最短的作业为其服务,但是又完全不考虑各个作业的等待时间,因此造成了对长作业不友好的问题,甚至还会造成饥饿的问题;所以为了既考虑到各个作业的等待时间,又能兼顾运行时间,提出了高响应比优先算法。

7.11.3 高响应比优先(HRRN,Highest Response Ratio Next)

在这里插入图片描述

以上几种调度算法一般适合用于早期的批处理系统,主要关心的是对用户的公平性、平均周转时间、平均等待时间等评价系统整体性能的指标。不适用交互式系统。

7.11.4 时间片轮转调度算法(RR,Round-Robin)

在这里插入图片描述

时间片太大,时间片轮转调度算法退化为先来先服务算法,并且会增大进程相应时间
时间片太小,会导致进程切换过于频繁,系统会花大量的时间来处理进程切换。

7.11.5 优先级调度算法

在这里插入图片描述
在这里插入图片描述

7.11.6 多级反馈队列调度算法

在这里插入图片描述
在这里插入图片描述

P1在第一级队列执行了一个时间片,未执行完,进入第二级队列队尾,P2在1时刻到达,进入第一级队列,P2运行1个时间片,进入第二级队列,此时为2时刻没有新进程到达,一级队列为空,运行二级队列队头P1,运行两个时间片,进入三级队列,4时刻运行二级队列中的进程P2,运行一个时间片后,P3到达,进入优先级更高的队列1,此时P2只运行了一个时间片,在5时刻被剥夺处理机,重新进入队列2队尾,之后P3运行1个时间片,结束,调出内存,之后运行P2,在二级队列运行两个时间片结束,调出内存,最后运行P1在三级队列4个时间片,未结束,在进入三级队列,再次运行。
在这里插入图片描述
本部分总结
在这里插入图片描述

7.12 进程同步和进程互斥

7.12.1 进程同步

进程具有异步性,异步性是指,各并发执行的进程以各自独立的、不可预知的速度向前推进。

但是有时又必须保证进程的执行顺序,也就是解决这种异步问题,就是进程同步。
同步亦称直接制约关系,它是指以完成某种任务而建立的两个或多个进程,这些进程因为需要在某些位置上协调它们的工作次序而产生的制约关系。

7.12.2 进程互斥

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.13 进程互斥的软件实现方法

7.13.1 单标志法

在这里插入图片描述
局限性
在这里插入图片描述

7.13.2 双标志法

在这里插入图片描述

7.13.3 双标志后检查法

在这里插入图片描述

7.13.4 Peterson算法

在这里插入图片描述
在这里插入图片描述
本部分总结
在这里插入图片描述

对所有问题的分析都可以采用这个思路:区分出哪个是进入区,在进入区做了哪些事情,然后再把进入区的操作在两个进程并发的情况下,以不同的顺序运行,验证进入区的操作在并发情况下会不会有问题。

7.14 进程互斥的硬件实现方法(不重要)

在这里插入图片描述

7.15 信号量机制

在这里插入图片描述

7.15.1 整型信号量

在这里插入图片描述

7.15.2 记录型信号量

在这里插入图片描述
在这里插入图片描述
本部分总结
在这里插入图片描述

7.16 用信号量机制实现进程互斥、同步、前驱关系

7.16.1 信号量机制实现进程互斥

在这里插入图片描述

7.16.2 信号量机制实现进程同步

在这里插入图片描述
在这里插入图片描述

7.16.3 信号量机制实现前驱关系

在这里插入图片描述
本部分总结(四大类问题)
在这里插入图片描述

7.17 生产者和消费者问题(互斥+同步综合问题)

在这里插入图片描述
在这里插入图片描述

PV操作题目分析步骤:

  1. 关系分析。找出题目中描述的各个进程,分析它们之间的同步、互斥关系。
  2. 整理思路。根据各进程的操作流程确定P、V操作的大致顺序。
  3. 设置信号量。设置需要的信号量,并根据题目条件确定信号量初值。(互斥信号量初值一般为1,同步信号量的初始值要看对应资源的初始值是多少)

生产者和消费者存在两个同步关系和一个互斥关系:
互斥关系: 缓冲区是临界资源,各进程必须互斥地访问;
**同步关系1:**缓冲区满时,生产者要等待消费者取走产品;
**同步关系2:**缓冲区空时,消费者要等待生产者放入产品;

生产者每次消耗(P)一个空闲缓冲区,并生产(V)一个产品;
消费者每次消耗(P)一个产品,并释放一个空闲缓冲区(V);
往缓冲区放入、取走产品需要互斥;
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
[重点] 实现互斥的P操作一定要在实现同步的P操作之后。
V操作不会导致进程阻塞,因此两个V操作顺序可以交换。

生产一个产品和使用产品可以放在P、V操作之间,但是这样会使得临界区的代码量变大,那么消费者在访问临界区的时候会需要更长的时间,那么此时如果有其他的进程要访问临界区,就会被阻塞,导致进程间的并发度降低。

在这里插入图片描述

7.18 多生产者和多消费者问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
问题:可不可以不用互斥信号量?(可以,即使不设置专门的互斥变量mutex,也不会出现多个进程同时访问盘子的现象)
在这里插入图片描述
原因在于本题中的缓冲区大小为1,在任何时刻,apple、orange、plate三个同步信号量中最多只有一个是1。因此在任何时刻,最多只有一个进程的P操作不会被阻塞,并顺利进入临界区…

如果把盘子的缓冲区设为2,就必须设置互斥量:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.19 吸烟者问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.20 读者和写着问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

潜在问题:只要有读进程还在读,写进程就要一直阻塞,可能“饿死”,因此,在上面这种算法中,是读进程优先的。
在这里插入图片描述
在这里插入图片描述

7.21 哲学家进餐问题

问题描述
一张圆桌上坐着5名哲学家,每两个哲学家之间的桌上摆一根筷子,桌子的中间是一碗米饭。哲学家们倾注毕生的精力用于思考和进餐,哲学家在思考时,并不影响他人。只有当哲学家饥饿时,才试图拿起左、右两根筷子(一根一根地拿起)。如果筷子已在他人手上,则需等待。饥饿的哲学家只有同时拿起两根筷子才可以开始进餐,当进餐完毕后,放下筷子继续思考。
在这里插入图片描述

  1. 关系分析。系统中有5个哲学家进程,5位哲学家与左右邻居对其中间筷子的访问是互斥关系。
  2. 整理思路。这个问题中只有互斥关系,但与之前遇到的问题不同的事,每个哲学家进程需要同时持有两个临界资源才能开始吃饭。如何避免临界资源分配不当造成的死锁现象,是哲学家问题的精髓。
  3. 信号量设置。定义互斥信号量数组 chopstick[5]={1,1,1,1,1} 用于实现对5个筷子的互斥访问。并对哲学家按0~4编号,哲学家 i 左边的筷子编号为i,右边的筷子编号为 (i+1)%5。

问题分析

  • 错误示范
semaphore chopstick[5]={1,1,1,1,1};
Pi (){ //i号哲学家的进程
	while(1){
		P(chopstick[i]); // 拿左
		P(chopstick[(i+1)%5]); // 拿右
		吃饭…
		V(chopstick[i]); // 放左
		V(chopstick[(i+1)%5]); // 放右
		思考…
	}
}

如果5个哲学家并发地拿起了自己左手边的筷子…
每位哲学家循环等待右边的人放下筷子(阻塞)。发生“死锁”

  • 正确姿势

① 可以对哲学家进程施加一些限制条件,比如最多允许四个哲学家同时进餐。这样可以保证至少有一个哲学家是可以拿到左右两只筷子的;
② 要求奇数号哲学家先拿左边的筷子,然后再拿右边的筷子,而偶数号哲学家刚好相反。用这种方法可以保证如果相邻的两个奇偶号哲学家都想吃饭,那么只会有其中一个可以拿起第一只筷子,另一个会直接阻塞。这就避免了占有一支后再等待另一只的情况;
③ 仅当一个哲学家左右两支筷子都可用时才允许他抓起筷子

思路三代码:

semaphore chopstick[5]={1,1,1,1,1};
semaphore mutex = 1; // 互斥地取筷子

Pi (){ //i号哲学家的进程
	while(1){
         P(mutex);
		P(chopstick[i]); // 拿左
		P(chopstick[(i+1)%5]); // 拿右
		V(mutex);
		吃饭…
		V(chopstick[i]); // 放左
		V(chopstick[(i+1)%5]); // 放右
		思考…
	}
}

假设一:哲学家0拿到了 筷子0 ,执行完P(chopstick[i]),切换到了哲学家2, 那么由于哲学家0执行了P(mutex),所以哲学家2被阻塞,知道0好哲学家顺利的拿到了 筷子1 , 再对mutex执行V操作之后,哲学家2可以被激活,拿起左边和右边的筷子。

假设2:哲学家0拿到了 筷子0 和 筷子1 ,正在吃饭,此时哲学家1尝试拿筷子1时,在阻塞P(chopstick[i]),然后这时哲学家2想拿到筷子, 阻塞在P(mutex),所以从这种情况来看,及时2号哲学家左右两边都有筷子,但是还是无法拿起两边的筷子。

假设3:哲学家0拿起左边和右边的筷子,之后哲学家4拿起左边的筷子,但是会阻塞在右边的筷子,这是哲学家4是拿了一直筷子,在等待别的筷子。

因此,这两种方法,并不能保证只有两边的筷子都可用时,才允许哲学家拿起筷子,所以更准确的说法应该是:各哲学家拿筷子这件事必须互斥的执行,这就保证了即使一个哲学家在拿筷子拿到一半时被阻塞,也不会有别的哲学家继续尝试拿筷子。这样的话,当前正在吃饭的哲学家放下筷子后,被阻塞的哲学家就可以获得等待的筷子。

本部分总结
在这里插入图片描述

八、管程

8.1 为什么要引入管程?

信号量机制存在的问题:编写程序困难、易出错

能不能设计一种机制,让程序员写程序时不需要再关注复杂的PV操作,让写代码更轻松呢?

1973年,Brinch Hansen 首次在程序设计语言 (Pascal)中引入了“管程”成分---------------------一种高级同步机制

8.2 管程的定义和基本特征?

  1. 组成

管程是一种特殊的软件模块,有这些部分组成:

  • 局部于管程的共享数据结构说明;
  • 对该数据结构进行操作的一组过程(函数);
  • 对局部于管程的共享数据设置初始值的语句;
  • 管程有一个名字。
  1. 特征
    管程的基本特征:
  • 局部于管程的数据只能被局部于管程的过程所访问;
  • 一个进程只有通过调用管程内的过程才能进入管程访问共享数据;
  • 每次仅允许一个进程在管程内执行某个内部过程。

8.3 拓展1:用管程解决生产者消费者问题

引入管程的目的无非就是要更方便地实现进程互斥和同步。

需要在管程中定义共享数据(如生产者消费者问题的缓冲区)
需要在管程中定义用于访问这些共享数据的“入口”——其实就是一些函数(如生产者消费者问题中,可以定义一个函数用于将产品放入缓冲区,再定义一个函数用于从缓冲区取出产品)
只有通过这些特定的“入口”才能访问共享数据
管程中有很多“入口”,但是每次只能开放其中一个“入口”,并且只能让一个进程或线程进入(如生产者消费者问题中,各进程需要互斥地访问共享缓冲区。管程的这种特性即可保证一个时间段内最多只会有一个进程在访问缓冲区 注意:这种互斥特性是由编译器负责实现的,程序员不用关心)
可在管程中设置条件变量及等待 / 唤醒操作以解决同步问题。可以让一个进程或线程在条件变量上等待(此时,该进程应先释放管程的使用权,也就是让出“入口”);可以通过唤醒操作将等待在条件变量上的进程或线程唤醒。

程序员可以用某种特殊的语法定义一个管程(比如 : monitor ProducerConsumer …… end monitor; ),之后其他程序员就可以使用这个管程提供的特定“入口”很方便地使用实现进程同步 / 互斥了。封装思想

8.4 拓展2:Java中类似于管程的机制

Java 中,如果用关键字synchronized 来描述一个函数,那么这个函数同一时间段内只能被一个线程调用

在这里插入图片描述
每次只能有一个线程进入insert 函数,如果多个线程同时调用insert 函数,则后来者需要排队等待

在这里插入图片描述

九 、死锁

在这里插入图片描述

9.1 什么是死锁?

在这里插入图片描述
在这里插入图片描述

9.2 死锁、饥饿、死循环的区别

在这里插入图片描述

9.3 死锁产生的四个必要条件

在这里插入图片描述

9.4 什么时候会发生死锁?

在这里插入图片描述

9.5 死锁的处理策略

在这里插入图片描述

9.5.1 预防死锁

① 破坏互斥条件
在这里插入图片描述
② 破坏不可剥夺条件
在这里插入图片描述
③ 破坏请求和保持条件
在这里插入图片描述
④ 破坏循环等待条件
在这里插入图片描述

9.5.2 避免死锁

① 什么是安全序列?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
② 安全序列、安全状态、不安全状态、死锁之间的联系
在这里插入图片描述
在这里插入图片描述
③ 避免系统进入不安全状态------银行家算法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
使用代码实现
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

9.5.3 死锁的检测和解除

在这里插入图片描述
① 死锁的检测
在这里插入图片描述
举个例子,可以消除所有边,即无死锁发生
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
举个例子,不可消除所有边,即产生死锁
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
② 死锁的解除
在这里插入图片描述
本部分总结
在这里插入图片描述

相关文章