死锁,进程间通信

本文深入探讨了死锁的概念,包括其发生的原因、必要条件及处理方法,如预防、避免、检测与恢复。同时,详细介绍了进程通信机制,涵盖信号、管道、消息队列、共享内存等,解析了直接与间接通信的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

死锁:由于竞争资源或者通信关系,两个或更多线程在执行中出现,永远相互等待只能由其他进程引发的事件

进程访问资源的流程是:请求/获取资源->使用资源->释放资源
资源分类:
1.可重用资源(Reusable Resource)
资源不能被删除且在任何时刻只能有一个进程使用
进程释放资源后,其他进程可重用
(处理器,I/O通道,主副存储器,设备,文件,数据库,信号量等)
可能出现死锁(每个进程占用一部分资源并请求其他资源)
2.消耗资源(Consumable resource)
资源创建和销毁
(在I/O缓冲区的中断,信号,消息等)
可能出现死锁(进程相互等待接受对方的消息)

出现死锁的必要条件
1.互斥(任何时刻只能有一个进程使用一个资源实例)
2.持有并等待(进程必须持有一个资源,并在等其他进程持有的资源)
3.非抢占(资源只能在进程使用完后自愿释放)
4.循环等待(0等1,1等2,2等3 … … n-1等n,n等0)

死锁的处理方法
1.死锁预防(Deadlock Prevention)
预防是采用某种策略,限制并发进程对资源的请求,使系统在任何时刻都不满足死锁的必要条件。
a.互斥(把互斥的共享资源封装成可同时访问)
b.持有并等待(进程请求资源时,要求它不持有任何其他资源 / 一次请求需要的所有资源)
c.非抢占(如请求不能立即分配的资源,则释放已占有资源 / 只有在能够同时获得所有需要的资源时,才执行分配操作)
d.循环等待(对资源排序,要求按顺序请求资源)
2.死锁避免(Deadlock Avoidance)
a.利用额外的先验信息,在分配资源时判断是否会出现资源,只在不会死锁时分配资源
b.要求进程声明需要资源的最大数目
c.限定提供与分配的资源数量,确保满足进程的最大需求
d.动态检查资源分配状态,确保不会出现环形等待
e.安全状态与死锁的关系:系统处于安全状态,一定没有死锁;系统处于不安全状态,可能出现死锁;避免死锁就是确保系统不会进入不安全状态。
f.银行家算法(Banker’s Algorithm)
银行家算法是一个避免死锁产生的算法。以银行借贷分配策略为基础,判断并保证系统处于安全状态。
——客户在第一次申请贷款时,声明所需最大资金量,在满足所有贷款要求并完后项目时,及时归还、
——在客户贷款数量不超过银行拥有的最大值时,银行家尽量满足客户需要
——银行家=操作系统;资金=资源;客户=申请资源的线程
在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

3.死锁检测和恢复(Deadlock Detection & Recovery)
允许系统进入死锁状态
死锁检测:
维护系统的资源分配图
定期调用死锁检测算法来搜索图中是否存在死锁
出现死锁时,用死锁恢复机制进行恢复
(死锁检测与银行家算法中的检测类似)
死锁恢复:进程终止
a.终止所有的死锁进程
b.一次只终止一个进程直到死锁消除
c.终止进程的顺序:按照进程优先级;进程已运行以及还需要运行的时间;进程已占用的资源;进程完成需要的资源;终止进程的数目;进程是用户的交互进程还是批处理
怎么终止呢? 资源抢占
选择被抢占进程(最小成本目标)
进程回退(返回到一些安全状态,重启进程待安全状态)
可能出现饥饿(同一进程可能一直被选作被抢占者)
4.由应用进程处理死锁(通常操作系统忽略死锁)

进程通信(IPC,Inter-Process Communication)
(1)进程通信是进程进行通信和同步的机制
(2)IPC提供两个基本操作
发送操作:send(message)
接受操作:receive(message)
(3)进程通信流程
再通信进程间建立通信链路
通过send/receive交换消息
(4)进程链路特征
物理(共享内存,硬件总线)
逻辑(逻辑属性)
(5)通信方式
间接通信/直接通信
在这里插入图片描述
a.间接通信
依赖操作系统内核来完成进程间通信
建立相应能够通信的机构,比如消息队列,进程A向消息队列发消息,进程B从消息队列读消息;进程的生命周期可以不一样。
b.直接通信
在两个进程之间建立通信信道
两进程直接通信,双方需要同时存在。
具体讨论:
直接通信:
——进程必须正确的命名对方
send(P,message):发送消息到进程P
receive(Q,message):从进程Q接收消息
——通信链路的属性:
自动建立链路
一条链路恰好对应一对通信进程
每对进程之间只有一个链路存在
链接可以是单向的,也可以是双向的
间接通信:
——通过操作系统维护的消息队列实现进程间通信
每个消息队列都有唯一标识
只有共享了相同消息队列的进程,才能通信
——通信链路的属性
只有共享了相同消息队列的进程,才建立连接
连接可以是单向的,也可以是双向的
消息队列可以与多个进程相关联
每对进程可以共享多个消息队列
——通信流程
创建一个新的消息队列
通过消息队列发送和接收消息
销毁消息队列
——基本通信操作
send(A,message):发送消息到队列A
receive(A,message):从队列A接收消息

阻塞与非阻塞通信
进程通信可划分为阻塞(同步)或非阻塞(异步)
阻塞通信:
——阻塞发送:发送者在发送消息后进入等待,直到接收者成功收到
——阻塞接收:接收方在请求接收消息后进入等待,直到成功收到消息
非阻塞通信:
——非阻塞发送:发送者在消息发送后,可立即进行其他操作
——非阻塞接收:没有消息发送时,接收者在请求接收消息后,接收不到任何消息,不等待,直接返回

通信链路缓冲
进程发送的消息在链路上可能有三种缓冲方式:
1.0容量
发送方必须等待接收方
2.有限容量
通信链路缓冲队列满时,发送方必须等待
3.无限容量
发送方不需要等待

下面来具体说明几种通讯机制:

信号和管道:
信号和管道是操作系统提供的两种简单的通信机制

信号(Signal)
进程间的软件中断通知和处理机制
信号的接收处理:
1.捕获(catch):执行进程指定的信号处理函数被调用
2.忽略(Ignore):执行操作系统指定的缺省处理;例如进程终止,进程挂起等
3.屏蔽(Mask):禁止进程接收和处理信号;可能是暂时的(当处理同样类型的信号)
特点:传送信息量很小,只有一个信号类型;比别的机制快
信号的实现:
在这里插入图片描述

管道(pipe)
进程间基于内存文件的通信机制(两个进程要通信,然后在内存里建一个临时文件,把数据放入这个文件里)
进程间基于内存文件的通信机制
——子进程从父进程继承文件描述符
——缺省文件描述符:0 stdin,1 stdout,2 stderr
进程不关心管道的另一端是谁(间接通信机制)
——数据可能来自于键盘,文件,其他进程
——数据可能写道终端,文件,其他进程

与管道相关的系统调用:
1.读管道:read(fd,buffer,nbytes)
scanf()是基于它实现的
2.写管道:write(fd,buffer,nbytes)
printf()是基于它实现的
3.创建管道:pipe(rgfd)
rgfd是2个文件描述符组成的数组
rgfd[0]是读文件描述符
rgfd[1]是写文件描述符

消息队列
消息队列是由操作系统维护的以字节序列为基本单位的间接通信机制
在这里插入图片描述
——每个消息(Message)是一个字节序列
——相同标志的消息组成按先进先出顺序组成一个消息队列(Message Queues)
消息队列的系统调用:
msgget(key,flags) //获取消息队列标识
msgsnd(QID,buf,size,flags) //发送消息
msgrcv(QID,buf,size,type,flags) //接收消息
msgctl(…) //消息队列控制
(一个进程创建了消息队列,进程结束了,消息队列仍可以存在下去,可以实现两个生命周期不同的进程间的通信)

共享内存
共享内存是把痛一个物理内存区域同时映射到多个进程的内存空间的通信机制
进程里:
——每个进程都有私有的内存地址空间
——每个进程的内存地址空间需明确设置共享内存段
线程里:
——同一进程中的线程总是共享相同的内存地址空间
优点:快速,方便的共享数据
缺点:必须用额外的同步机制来协调数据访问(防止一个进程还没写完,另一个就进去读)

共享内存的实现:
在这里插入图片描述
共享内存的系统调用:
shmget(key,size,flags) //创建共享段
shmat(shmid,*shmaddr,flags) //把共享段映射到进程地址空间
shmdt(*shmaddr) //取消共享段到进程地址空间的映射
shmctl(…) //共享段控制
(需要信号量等机制协调共享内存的访问冲突)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值