`
wangminshe89
  • 浏览: 668358 次
文章分类
社区版块
存档分类
最新评论

进程间通信

 
阅读更多

进程间通信

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

临界区:对共享内存进行访问的程序片段。

进程通信有三方面的内容:

1.一个进程如何向另一个进程场地消息
2.必须保证多个进程在涉及临界活动时不会彼此影响(设想两个进程都试图摄取最后100kb内存的情况)。
3.当存在依赖关系时确定适当的次序:如果进程A产生数据,进程B打印数据,则B必须等到A产生了一些数据后才能开始打印。

由于存在共享内存,并且有多个进程要进行读写操作,那么如何保证不发生错误(避免竞争)?解决的方法是互斥(mutual exclusion),即以某种手段确保当一个进程在使用一个共享变量或文件时,其他的进程不能做同样的操作。

那么如何设计一个好的互斥方案?一个好的互斥解决方案,需要具备以下四个条件:

1.任何两个进程不能同时处于临界区
2.不应对CPU的速度和数目做任何假设
3.临界区外的进程不得阻塞其他进程
4.不得使进程在临界区外无休止的等待

解决方案1:关闭中断

缺点:假如用户进程关闭中断后就不开中断,系统可能会因此而终止。

关中断对于操作系统来说是一项有用的技术(内核在执行更新变量时发生中断,那么可能会导致竞争条件,因为cpu本身就是共享资源),对用户则不是一种合适的通用互斥机制。

解决方案2:锁变量(只是最简单的,也是最容易想到的)

设置一个共享锁变量,初值为0,当要访问该资源是,检查这把锁的状态。但是这种方案不行,有可能两个进程都把该锁设置为相同的状态,导致竞争条件。有多个进程同时把所变量设为相同的值,具体写代码实现就很清楚

解决方案3:严格交替法(轮流进入临界区,可行)

这是对锁变量的方案进行改进,把锁设置为0交个一个进程,把锁设置为1交个另一个进程。 也就是说一个进程只能对锁设置一种状态。

缺点:假如A进程把锁设置为1后离开临界区以便允许其他进程进入临界区,但A很快又请求进入临界区,此时A得等待有其他进程把锁设置为0,A方可进入。如果没有其他进程来更新锁的状态,那么A就得一直等待下去(忙等待),不管怎么样,A的等待是不可避免的。只有在有理由期待等待时间很短时才使用忙等待,一个适用忙等待的锁称为自旋锁(spinlock)。

解决方案4:Peterson方案

严格交替法失效的原因在于,A必须等待到有进程进入临界区更新锁的状态,然后才能进入。怎么来改进这种方案呢?A等待是因为其他进程不在临界区,所以A被临界区外的进程阻塞。假如此时A知道其他进程的状态,那么它就不需要等待。如何来实现?

缺点:存在忙等待,等待临界区的进程离开

实现:

解决方案5:睡眠(sleep)和唤醒(wakeup)

如何避免忙等待?Peterson解法的本质是,当一个进程想进入临界区,先检查是否允许进入,若不允许,则进程忙等待,直到许可为止。这种情况可能会出现一个严重的错误,永远忙等待下去。

如何来改进这一算法?一种简单的想法是,当检测到不能进入临界区的话,那么该进程就应当让出cpu(把自己阻塞),执行另外的一个进程,而不是占着cpu。那么如何实现?使用sleep和wakeup系统调用。

实现:

缺点:引发上述wakeup信号丢失的原因是对count的访问未加限制。如何来解决信号丢失问题,一种快速补救的方法是,加上一个唤醒等待位(wakeup waiting bit) 。但这种方法的缺点是,假如有多个进程,那么一个唤醒等待我就不够了。

解决方案5:信号量

针对上述wakeup信号量丢失的问题,如何解决?上述问题的根本原因是不需要唤醒的时候去唤醒。

信号量是E.W.Dijkstra在1965年提出的一种方法,它使用一个整型变量来累计唤醒次数,以供以后使用。在他的建议中,引入一个新的变量,称为信号量(semaphore)。

Dijkstra建议设两种操作:P和V(分别为一般后的sleep和wakeup)。对一信号量执行P操作首先检查其值是否大于0,如果这样,则将其值减一(即用掉一个保存的唤醒信号)并继续。如果为0,则进程睡眠。检查数值、改变数值以及可能发生的睡眠操作均作为一个单一的、不可分割的原子操(atomicaction)作完成。

V操作递增信号量。如果一个或者多个进程在该信号量上睡眠,无法完成一个先前的P操作,则由系统选择其中的一个并允许其它的P操作。于是,对一个有进程在其上睡眠的信号量执行一次V操作之后,该信号量仍旧是0,但在其上睡眠的进程却少了一个。

如果每个进程在进入临界区前执行P操作,离开临界区后执行V操作,那么就能保证互斥。

信号量可能的使用方法:

互斥:初始化互斥信号量为1
共享资源:初始化信号量为共享实体的数量
协作进程:初始化信号量为0

用信号量解决生产者消费者问题:


总结:实现互斥,本质是把对信号量的递增和递减操作分隔开,一个进程只能进行一种操作,并且是原子操作。

解决方案6:管程

有了信号量之后,进程间通信看来很容易了吗?使用信号量需要程序员考虑时间问题,如何安排P的顺序(如果安排不但则会死锁),这样很容易错过一些问题,导致debug很困难。所以,一种好的方法是,把如何安排互斥的问题交给编译器来处理,即设计一种高级同步原语,称为管程。

分享到:
评论

相关推荐

    linux进程间通信与同步.pdf

    Linux系统中的进程间通信是典型的虚拟内存系统中的进程间通信:Linux 的进程间通信是不同进程间交换数据的机制。由于Linux系统支持虚拟内 存, 对于每一个进程,系统会为它分配一个单独的进程空间,不同的进程有不同...

    C# 进程间通信 共享内存

    共享内存,顾名思义就是允许两个不相关的进程访问同一个逻辑内存,共享内存是两个正在运行的进程之间共享和传递数据的一种非常有效的方式。...1、进程间通信 2、共享内存 3、托管方式与非托管共享内存

    UNIX网络编程_卷2_进程间通信

    卷2:进程间通信(第2版)》是一部UNIX网络编程的经典之作!进程间通信(IPC)几乎是所有Unix程序性能的关键,理解IPC也是理解如何开发不同主机间网络应用程序的必要条件。《UNIX网络编程.卷2:进程间通信(第2版)》从对...

    进程间通信之信号 sinal ) 完整代码

    进程间通信之信号 sinal ) 唯一的异步通信方式 七种进程间通信方式: 一 无名管道( pipe ) 二 有名管道( fifo ) 三 共享内存 shared memory 四 信号 sinal 五 消息队列 message queue ) 六 信号量 ...

    UNIX网络编程第二卷 进程间通信

    UNIX网络编程第二卷 进程间通信

    C#进程间通信

    操作系统实验之进程间通信(管道方式)。 内涵实验源码及报告文档。 更详尽内容请参考小魏博客:http://blog.csdn.net/xiaowei_cqu/article/details/7041212

    C#使用SendMessage实现进程间通信的方法

    本文实例讲述了C#使用SendMessage实现进程间通信的方法。分享给大家供大家参考。具体分析如下: 为了深入理解消息机制,先来做一个测试项目 在新建项目的Form1的代码中,加入方法: protected override void ...

    Messenger进程间通信

    Messenger进程间通信,包括Service服务端代码和客户端代码;进程内部通信/进程间通信并且应答;

    进程间通信之套接字( socket )——完整代码

    进程间通信之套接字( socket ) 网络间通信 七种进程间通信方式: 一.无名管道( pipe ) 二.有名管道( fifo ) 三.共享内存 ( shared memory ) 四.信号 ( sinal ) 五.消息队列 ( message queue ) 六.信号量 ( ...

    操作系统进程间通信实验

    通过对进程间通信同步/互斥问题的编程实现,加深理解信号量和 P、V 操作的原理; 对 Windows 或 Linux 涉及的几种互斥、同步机制有更进一步的了解;熟悉 Windows 或 Linux 中定义的与互斥、同步有关的函数。

    Linux进程间通信

    Linux进程间通信

    Linux进程间通信.pdf

    Linux进程间通信.pdf Linux进程间通信.pdf

    Linux环境进程间通信(五) 共享内存(上)

    Linux环境进程间通信(五) 共享内存(上)

    Qt进程间通信与同步示例

    Qt进程间通信与同步示例,通过QFile内存映射文件来共享内存达到进程间通信的效果。同时利用QSystemSemaphore 来实现进程同步

    操作系统实验报告(LINUX进程间通信)

    操作系统实验报告(LINUX进程间通信)

    进程间通信的VC++源码实例集,邮槽、匿名管道等

    进程间通信的VC++源码实例集,进程之间的通信以及实现方法实例,通过一些小程序来实现,这些小程序有剪贴板实例、邮槽、匿名管道等,希望对VC++基础用户有帮助。

    利用内存映射文件技术实现进程间通信

    利用内存映射文件技术实现进程间通信,自pudn程序员联合开发网下载

    进程间通信例子

    进程间通信,可以在winform下两个进程,收信息,发信息。很实用的一个例子。

Global site tag (gtag.js) - Google Analytics