进程通信

来源:互联网 发布:淘宝购物怎么走返利 编辑:程序博客网 时间:2024/05/20 02:26

Hey,Guys! 给我发条消息吧?

我们知道,无论是在进程互斥还是进程同步中,所有的进程都交换了消息——一个简单的唤醒信号。
虽然只是一个简单的消息,但我们依旧可以将其划分到进程通信中,作为一种低级通信看待(蚊子再小也是肉嘛!)。
有低级通信,那自然也就有高级通信,不过一般而言,我们所说的进程通信都是指高级通信,毕竟互斥和同步都有自己专属的称呼。

  • 进程通信
    • 进程通信的模式
    • 基于消息传递的实现
      • 直接方式
      • 消息传送的途经
      • 间接方式
  • 小结

进程通信


进程间的互斥,同步以及信息交换统称为进程通信

进程通信的模式

  1. 共享内存模式

    • 相互通信的进程之间有公共内存,这个公共内存是操作系统分配和管理的,而其使用和基于此的信息传递则是相互通信的进程自己完成的。
    • 由于是基于公共内存,故而对其访问需要提供必要的同步机制(等价于共享变量)。

    小的时候做过一个传声器,两个纸杯加上一根绳子就可以制作了,但问题就是两个纸杯共用一根绳子,我和朋友只能是一个说,一个听,要不然就听不到对方再说什么了。

  2. 消息传递模式
     
    在此种模式下的信息传递是不需要公共内存的。操作系统提供提供发送命令(send)和接收命令(receive)这两个系统调用命令来进行消息传递(通信)。

    发生消息传递时,只需通信的进程调用这两个命令即可。由于这两个命令是由操作系统提供的,所以命令内部的实现对于用户是透明的。
    就像我们打电话,只需要会打电话,会接电话就好了,除了研究这个技术的人,谁会关心怎么实现的这个技术呢?

基于消息传递的实现

直接方式

在这种方式下,进程会直接指定消息源或者接受方,类似于函数的映射,有一对一和多对一的类型。

  • 一对一,即对称形式
    对称形式

  • 多对一,即非对称形式
    非对称形式

    高中学数学,最痛苦的就是函数的映射关系,开始的时候一看,哎呀,挺简单的,理解了,然后老师上课提问映射的关系……
    咦?映射,什么玩意儿?!
    浑浑噩噩一个学期之后,什么1-1映射,慢射之类的,还是挺模糊的,不懂,于是就听同桌说,画个函数图像啦,balabala一堆之后,终于懂了。
    于是整个高中三年,遇到映射就画个图像……

消息传送的途经

  1. 带缓冲的途经
    高级语言进行文件读写的时候似乎都有带缓冲和不带缓冲的读写?带缓冲流程序开销小,这是由于不需要频繁的进入磁盘读取文件,进程的消息传递也是这样的。
    带缓冲的send和receive的具体实现

    send和receive命令都是操作系统提供的,使用的时候是要进入操作系统的,而这两者进入操作系统是靠进程产生的自愿性中断实现的。而且有个缓冲区,只需中断一次,读取完消息,回到用户态就可以继续向下执行其他的程序,不用不断的中断读取,直到读取完毕。

  2. 不带缓冲
    不带缓冲的send和receive的具体实现

    这看其来可比带缓冲的简单太多了,而且没有了缓冲区,也就节省了空间,但是由于要等待接收进程完成消息接收后才能让发送进程继续推进,这样看来并发性着实太弱了。

间接方式

间接方式和直接方式相对应,是存在媒介进行信息的交换——通信,不需要指明进程具体是哪一个,只需要指明相互通信的进程使用的中间媒介。
这个中间媒介在操作系统中被描述为信箱,所以间接方式也成为信箱方式,在实现这种方式时,信箱既可以属于操作系统空间,也可以是属于用户进程空间,但关于信箱操作的命令则是操作系统提供的(系统调用命令),属于操作系统,来看看关于信箱的定义:

typedef struct mailbox{    int in, out;      //读写内容的位置,初始为0    int k;      //消息的个数    semaphore s1, s2;     //协调发送和接收的信号量初始为k和0    semaphore mutex;    //用于各进程进入信箱的互斥    message letter[k];         //信箱,保存k个消息}MailBox;

对于信箱的操作定义:

send_MB(MailBox A, message M){    P(A.s1);    P(A.mutex);    A.letter[A.in] = M;    A.in = (A.in + 1) % A.k;    V(A.mutex);    V(A.s2);}receive_MB(MailBox A, message N){    P(A.s2);    P(A.mutex);    N = A.letter[A.out];    A.out = (A.out + 1) % A.k;    V(A.mutex);    V(A.s1);}

send_MB和receive_MB只是关于信箱的四个命令之一,因为还要创建和删除嘛!
信箱命令的使用权限

话说,朋友之间吵架冷战算是很正常的事情吧?
我上高中那会儿和同桌不知道因为啥原因吵了一架,然后就开始冷战,到后来一次班上六人一组讨论问题(我们开玩笑说这是圆桌会议),关于一个问题又出现分歧,然后我就伸手随便拉住某个人说:“她是不是傻!alabala…..”,我同桌又拽着他:“你告诉他,这么简单的逻辑问题都出错,明显是他傻!”……
想想那兄弟可能也挺无奈的,你说两人都能听到对方说话,还非要找第三人来当传声筒……

小结


在进程通信的模式选择上,没有完美,只有适合于不适合,即便我们说无缓冲的通信并发性差,开销还大,但是耐不住人家实现简单啊,在一些简单的问题实现上和带缓冲的通信差距并不大,那为何要选择带缓冲的通信方式呢?杀鸡焉用牛刀?
这条经验,不仅仅适用于进程通信上,几乎什么事情,这条经验都是实用的。

Hey! Guys! 我发了条消息给你,收到了吗?

原创粉丝点击