您的位置:首页 > 其它

二、进程间通信

2016-05-03 17:10 183 查看
2.3 进程间通信

1) 一个进程如何把消息传递给另一个进程

2) 确保两个或更多的进程在关键活动中不会出现交叉

3) 进程间的正确执行顺序

后两个问题对于线程来说同样适用。由于共享内存空间,线程间的消息传递比较容易。

2.3.1 竞争条件

协作的进程可能共享一些彼此都能读写的公用存储区,可能在内存中也可能是某个共享文件。两个或更多的进程读写某些共享数据,最终的结果取决于进程的精确时序,称为竞争条件。

2.3.2 临界区

凡涉及共享内存、共享文件或共享任何资源的情况都会引发竞争条件的错误。需要找出某种途径来阻止多个进程同时读写共享的数据,即需要互斥(为实现互斥而选择适当的原语是操作系统的主要设计内容之一)。把对共享资源进行访问的程序标段称为临界区,需要使得两个进程不可同时处于临界区中,从而避免竞争条件。

解决竞争条件的方案需要满足以下条件:

1) 任何两个进程不能同时处于其临界区;

2) 不应对CPU的速度和数量做出任何假设;

3) 临界区外的进程不得阻塞其他进程;

4) 不得使进程无限期等待进入临界区。

2.3.3 忙等待的互斥

a) 屏蔽中断

单处理器系统中,可以使每个进程进入临界区后立即屏蔽所有中断,离开前打开中断。屏蔽中断后,CPU不会被切换到其他进程。

b) 锁变量

设置一个共享锁变量,初始值为0。当进程想要进入临界区时,首先测试锁变量,为零则将锁变量置1,并进入临界区。若为0,则等待该锁变量变为1。该方案存在竞争条件一样的漏洞。

c) 严格轮换法

设置一个共享的锁变量turn,初始值为0,用于记录轮到哪个进程进入临界区,其值表示轮到哪个进程进入临界区。这种方式需要进程连续测试一个变量直到某个值的出现,称为忙等待,用于忙等待的锁称为自旋锁。

在一个进程比另一个进程慢了很多的情况下,轮流进入临界区违反了第三条:临界区外的进程阻塞了其他进程,会造成CPU的浪费。

d) Peterson解法

该解法用turn标识现在轮到哪个进程想要进入临界区,用一个数组interested[]表示进程是否在临界区。

e) TSL指令(测试并加锁)

该方法需要硬件支持,TSL RX,LOCK称为测试并加锁。将内存字lock读到寄存器中,并在该内存字上存一个非零值。两步操作是不可分割的,即该指令借宿之前其他处理器不允许访问该内存字(该指令将锁住内存总线)。

XCHG指令可以替代TSL指令。

2.3.4 睡眠与唤醒

上述的Peterson解法与TSL指令都可以解决竞争条件的问题,但是他们是忙等待的,会造成CPU资源的浪费,还会造成优先级反转的问题。

一些进程间通信原语可以使得进程在无法进入临界区时产生阻塞而不是忙等待。如sleep和wakeup。

l 生产者-消费者问题(界缓冲区问题)

两个(或多个)进程共享一个公共的固定大小的缓冲区,其中一个是生产者—将信息放入缓冲区,另一个是消费者—从换中去取出消息。当缓冲区已满时,生产者还想放入新的信息则需要将其睡眠,等消费者从换中去取出一个或多个信息后再唤醒他;同样对于消费中试图从空的缓冲区中取出信息时也应将其睡眠。

会有wakeup信号丢失的问题。可以用一个变量保存wakeup信号。

2.3.5 信号量

一个信号量的取值可以为0或者正值,0表示没有保存的唤醒操作,正值表示一个或多个唤醒操作。

down和up操作,down操作将信号量减1,若信号量为0则将进程休眠;up操作将信号量的值加1,若一个或多个进程字该信号量上睡眠,无法完成一个先去的down操作,则有系统选择一个进程完成他的down操作(此时信号量的值又成为0)。Down和up操作也是一对具有原子性的操作。在多CPU系统中,需要用TSL或XCHG指令来确保同一时刻只有一个CPU在对信号量进行操作。

2.3.6 互斥量

互斥量为信号量的简化版本,只有0和1两个值,及取消了信号量的计数功能。一般用于用户空间线程包的调用。

mutex_lock和mutex_unlock操作实现互斥量的加锁和解锁功能(有时还有mutex_trylock操作,用来获得所或失败码而不阻塞线程)。

共享一个公共地址空间的两个进程仍有个字的打开文件、报警定时器和其他一些单个进程的特性(共享全部或者大部分地址空间的进程与线程的区别)。

2.3.7 管程

使用信号量不当容易产生死锁的问题。为了更易于编写正确的程序,提出了一种高级同步原语,称为管程。任一时刻管程中智能有一个活跃进程,使得管程能够有效地完成互斥。进入管程的互斥由编译器负责。

管程完成互斥问题,而进程无法继续运行时被阻塞有条件变量以及条件变量的两个操作:wait和signal解决。Wait操作导致进程自身阻塞并将另一个以前等待在管程之外的进程调入管程。Signal操作能够唤醒正在睡眠的伙伴进程。条件变量不能像信号量那样积累信号以便以后使用。也就是说wait操作要处于signal操作之前,否则信号会丢失。

通过临界区互斥的自动化,管程比信号量更容易保证并行编程的正确性。

u 如果一个分布式系统具有多个CPU,并且每个CPU拥有自己的私有内存,则以上的原语都会失效。

2.3.8 消息传递

消息传递使用send和receive两条原语,他们是系统调用(如信号量)而不是语言成分(如管程)。为了防止消息被网络丢失,接收方一旦接收消息马上回送一条确认消息(ACK)。发送方一段时间没有接收到确认消息则重发该消息。

2.3.9 屏障

该机制用于进程组,所有的进程都就绪才进入下一个阶段,否则任何进程都不进入下一个阶段。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: