进程间通信

220 阅读5分钟

进程间通信

竞争条件

两个或多个进程读写某些共享数据,而最后的结果取决于进程运行的精确时序,称为竞争条件。

临界区

对共享内存进行访问的程序片段称作临界区域。 避免竞争条件解决方案的四个条件: 任何两个进程不能同时处于其临界区。 不应对CPU的速度和数量做任何假设。 临界区外运行的进程不得阻塞其他进程。 不得使进程无限期等待进入临界区。

忙等待的互斥

忙等待可能造成优先级反转

  1. 屏蔽中断(只能屏蔽当前CPU)
  2. 锁变量
  3. 严格轮换法 连续测试一个变量直到某个值出现为止,称为忙等待。这种方式浪费CPU时间,通常应该避免。只有在有理由认为等待时间是非常短的情形下,才使用忙等待。用于忙等待的锁,称为自旋锁。
  4. Peterson解法
  5. TSL指令(test and set lock) 硬件方案

睡眠与唤醒

进程通信原语:sleep和wakeup

信号量

三个信号量实现生产者—消费者问题 full empty mutex

互斥量

如果不需要信号量的计数能力,有时可以使用信号量的一个简化版本,称为互斥量。

  1. 快速用户区互斥量futex
  2. pthread中的互斥量

管程

管程是一个语言概念,只有少数语言实现了管程。 管程是一个过程,变量及数据结构组成的一个集合。 同一时刻只能有一个线程进入管程。 信号量操作是成对出现的,管程只需要包装一个过程。

消息传递

管程和信号量是用来解决访问公共内存的一个或多个CPU上互斥的问题。如果一个分布式系统具有多个CPU,并且每个CPU拥有自己的私有内存,他们通过一个局域网项链,那么这些原语将失效。并且这些原语没有解决机器间的信息交换方法。 上面提到的方法就是消息传递。

屏障

除非所有进程就绪准备着手下一个阶段,否则任何进程都不能进入下一个阶段,可以通过在每一个阶段的结尾安置屏障来实现这种行为。

避免锁:读-复制-更新

确保每个读操作要么读取旧的数据版本,要么读取新的数据版本,但绝对不能时新旧数据的一些奇怪组合。

调度

多个进程或线程争夺一个CPU时,选择下一个要运行的进程工作称为调度程序,改程序使用的算法称为调度算法。

调度简介

  1. 进程行为 几乎所有进程的(磁盘或网络)I/O请求和计算都是交替突发的。当一个进程等待外部设备完成工作而被阻塞时,才是I/O活动。 花费了绝大多数时间在计算上的是计算密集型,花费了绝大多数时间在I/O上的是I/O密集型。
  2. 何时调度 在创建一个新进程之后 在一个进程退出时必须做出调度决策 在一个进程阻塞在I/O和信号量上或由于其他原因阻塞时 在一个I/O中断发生时 根据如何处理时钟中断,可以把调度算法分为两类:非抢占式和抢占式
  3. 调度算法分类 三种环境:批处理,交互式,实时。
  4. 调度算法的目标 所有系统 公平-给每个进程公平的CPU份额 策略强制执行-保证规定的策略被执行 平衡-保持系统的所有部分都忙碌 批处理系统 吞吐量-每小时最大作业数 周转时间-从提交到终止间的最小时间 CPU利用率-保持CPU始终忙碌 交互式系统 响应时间-快速响应请求 均衡性-满足用户的期望 实时系统 满足截止时间-避免丢失数据 可预测性-在多媒体系统中避免品质降低

批处理系统调度

  1. 先来先服务
  2. 最短作业优先
  3. 最短剩余时间

交互式系统中的调度

  1. 轮转调度
  2. 优先级调度
  3. 多级调度
  4. 最短进程优先
  5. 保证调度
  6. 彩票调度
  7. 公平分享调度

实时系统中的调度

实时系统分为硬实时和软实时 实时系统按事件响应方式分类分为周期性和非周期性 满足一定条件的实时系统是可调度的

策略和机制

调度机制与调度策略分离,将调度算法参数化

线程调度

用户级线程:不同进程中的线程调度相互独立,内核选取进程 内核级线程:内核选取线程 用户及线程切换只需要少量的机器指令,而内核级线程需要完成的上限文切换

经典的IPC问题

哲学家就餐问题

拿起左叉,查看右叉是否可用,如果不可用等待随机时间放下左叉,重复整个过程。此方案依赖随机数,不完全可靠。 使用一个二元信号量对调用think之后的五个语句进行保护。有性能问题。 使用一个数字跟踪一个哲学家是在进餐,思考还是饥饿。以哲学家的状态判断叉子的状态。从以叉子为核心到以哲学家为核心。

读者-写者问题

读写锁,写者等待当前正在工作的读者。