第十二章 死锁和进程通信
12.1 死锁概念
-
死锁是由于竞争资源或者通信关系,两个或更多线程在执行中出现,永远相互等待只能由其他进程引发的事件。
-
进程访问资源的流程
-
资源分类
- 可重用资源
- 资源不能被删除,且任何时刻只能有一个进程使用
- 可能出现死锁
- 每个进程占用一部分资源并请求其他资源
- 可重用资源示例
- 硬件:处理器,I/O通道,主和副存储器,设备等
- 软件:文件,数据库和信号量等数据结构
- 进程释放后,其他进程可以重用
- 消耗资源
- 资源创建和销毁
- 消耗资源示例
- 在I/O缓冲区的中断,信号,消息等
- 可能出现死锁
- 进程间相互等待接收对方的消息
- 可重用资源
-
资源分配图
- 描述资源和进程间的分配和占用关系的有向图
- 资源分配图示例
- 不存在死锁
- 会出现死锁
- 不会出现死锁
出现死锁的必要条件
当同时满足以下条件时,才会出现死锁
- 互斥:不是共享资源,只能一个进程同时使用
- 持有并等待:进程持有至少有一个资源,并正在等待获取其他进程持有的资源
- 非抢占:资源只能在进程使用后自愿释放
- 循环等待:存在循环等待
12.2 死锁处理方法
- 死锁预防:确保系统永远不会进入死锁状态。 限制死锁的申请资源
- 死锁避免:在使用前进行判断,只允许不会出现死锁的进程请求资源。 申请资源需要满足条件
- 死锁检测和恢复:在检测到运行系统进入死锁状态后,进行恢复。
- 由应用进程处理死锁
- 通常操作系统忽略死锁
- 大多数操作系统(包括UNIX)的做法
死锁预防:限制申请方式
-
预防是采用某种策略,限制并发进程对资源的请求,使系统在任何时刻都不满足死锁的必要条件
-
互斥
- 把互斥的共享资源封装成可同时访问
-
持有并等待:
- 进程请求资源时,要求它并不持有任何其他资源
- 仅允许进程在开始执行时,一次请求所有需要的资源
- 资源利用率低
-
非抢占
- 如进程请求不能立即分配的资源,则释放已占有资源
- 只在能够同时获得所有需要资源时,才执行分配操作
-
循环等待
- 对资源排序, 要求进程按顺序请求资源,也会有效率低的问题
死锁避免
- 利用额外的先验信息,在分配资源时判断是否会出现死锁,只在不会死锁时分配资源
- 系统资源分配的安全状态
- 安全状态与死锁的关系
12.3 银行家算法
- 银行家算法是著名的死锁避免算法
- 银行家算法:安全状态判断
-
银行家算法
-
银行家算法示例
- 先用Max减去Allocation矩阵得到Need矩阵
- 将Availabe向量与Need矩阵各行相比,找出比Availiable向量更小的行向量
- 选择满足条件的一个行向量对应的进程,释放分配给他的资源
- 更新Max和Allocation矩阵和行向量Available向量,重复上诉操作,得到安全序列
12.4 死锁检测
- 允许系统进入死锁状态
- 维护系统的资源分配图
- 定期调用死锁检测算法来搜索图中是否存在死锁
- 出现死锁时,用死锁恢复机制进行恢复
-
死锁检测算法:数据结构
-
死锁检测算法
-
死锁检测示例
-
死锁检测算法的使用
- 死锁检测的时间和周期选择依据
- 死锁多久可能会发生
- 多少进程需要被回滚
- 资源图可能有多个循环
- 难于分辨“造成”死锁的关键进程
- 死锁检测的时间和周期选择依据
-
死锁恢复:进程终止
- 死锁恢复:资源抢占
12.5 进程通信(IPC,Inter-Process Communication)概念
- 进程通信是进程进行通信和同步的机制
- IPC提供2个基本操作
- 发送操作:send(message)
- 接收操作:receive(message)
- 通信方式
- 间接通信:两个进程的生命周期可以不一样
- 直接通信:两个进程必须同时存在才能够进行通讯
- 直接通信
- 间接通信
- 间接通信
- 阻塞与非阻塞通信
-
进程通信可分为阻塞(同步)或非阻塞(异步)
-
阻塞通信
- 阻塞发送:发送者在发送消息后进入等待,直到接收者成功收到
- 阻塞接收:接收者在请求接收消息后进入等待,直到成功收到一个消息
-
非阻塞通信
- 非阻塞发送:发送者在消息发送后,可立即进行其他操作
- 非阻塞接收:没有消息发送时,接收者在请求接收消息后,不用等待直接返回
-
通信链路缓冲
12.6 信号和管道
- 信号
- 进程间的软件中断通知和处理机制
-
缺省:即系统默认状态,意思与“默认相同”
-
信号的使用示例
-
管道
- 进程间基于内存文件的通信机制
- 进程间基于内存文件的通信机制
-
与管道相关的系统调用
- 管道示例
12.7 消息队列和共享内存
消息队列
- 消息队列是由操作系统维护的以字节序列为基本单位的间接通信机制
- 每个消息(Message)是一个字节序列
- 相同标识的消息组成按先进先出顺序构成一个消息队列
- 消息队列的系统调用
- 一个进程可以创建一个消息队列,但是这个进程结束了,消息队列还可以继续存在下去,从而可以实现两个不同生命周期的进程进行通信
共享内存
- 共享内存是把同一个物理内存区域同时映射到多个进程的内存地址空间的通信机制
- 共享内存的实现机制
- 共享内存系统调用