linux进程间通信

深刻理解Linux 进程间通信(IPC)
作者:郑彦兴

一个大型的应用系统,往往需要众多进程协作,进程(Linux进程概念见附1)间通信的重要性显而易见。本系列文章阐述了Linux环境下的几种主要 进程间通信手段,并针对每个通信手段关键技术环节给出详细实例。为达到阐明问题的目的,本文还对某些通信手段的内部实现机制进行了分析。



linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的。而对Unix发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在 进程间通信方面的侧重点有所不同。前者对Unix早期的 进程间通信手段进行了系统的改进和扩充,形成了“system V IPC”,通信进程局限在单个计算机内;后者则跳过了该限制,形成了基于套接口(socket)的 进程间通信机制。Linux则把两者继承了下来,其中,最初Unix IPC包括:管道、FIFO、信号;System V IPC包括:System V消息队列、System V信号灯、System V共享内存区;Posix IPC包括: Posix消息队列、Posix信号灯、Posix共享内存区。有两点需要简单说明一下:1)由于Unix版本的多样性,电子电气工程协会(IEEE)开发了一个独立的Unix标准,这个新的ANSI Unix标准被称为计算机环境的可移植性操作系统界面(PSOIX)。现有大部分Unix和流行版本都是遵循POSIX标准的,而Linux从一开始就遵循POSIX标准;2)BSD并不是没有涉足单机内的 进程间通信(socket本身就可以用于单机内的 进程间通信)。事实上,很多Unix版本的单机IPC留有BSD的痕迹,如4.4BSD支持的匿名内存映射、4.3+BSD对可靠信号语义的实现等等。

linux 所支持的各种IPC手段,在本文接下来的讨论中,为了避免概念上的混淆,在尽可能少提及Unix的各个版本的情况下,所有问题的讨论最终都会归结到Linux环境下的 进程间通信上来。并且,对于Linux所支持通信手段的不同实现版本(如对于共享内存来说,有Posix共享内存区以及System V共享内存区两个实现版本),将主要介绍Posix API。

linux下 进程间通信的几种主要手段简介:

管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;
信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于 进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数);
报文(Message)队列(消息队列):消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
套接口(Socket):更为一般的 进程间通信机制,可用于不同机器之间的 进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。
下面将对上述通信机制做具体阐述。

附1:参考文献[2]中对linux环境下的进程进行了概括说明:

一般来说,linux下的进程包含以下几个关键要素:

有一段可执行程序;
有专用的系统堆栈空间;
内核中有它的控制块(进程控制块),描述进程所占用的资源,这样,进程才能接受内核的调度;
具有独立的存储空间
进程和线程有时候并不完全区分,而往往根据上下文理解其含义。

参考文献:

UNIX环境高级编程,作者:W.Richard Stevens,译者:尤晋元等,机械工业出版社。具有丰富的编程实例,以及关键函数伴随Unix的发展历程。
linux内核源代码情景分析(上、下),毛德操、胡希明著,浙江大学出版社,提供了对linux内核非常好的分析,同时,对一些关键概念的背景进行了详细的说明。
UNIX网络编程第二卷: 进程间通信,作者:W.Richard Stevens,译者:杨继张,清华大学出版社。一本比较全面阐述Unix环境下 进程间通信的书(没有信号和套接口,套接口在第一卷中)。
 

4.7 进程通信(IPC, Inter-Process Communication)

通信(communication)意味着在进程间传送数据。操作系统可以被看作是各种进程组成的,例如用户进程、计算进程、打印进程等。这些进程都具有各自独立的功能,且大多数被外部需要而启动执行。一般来说,进程间的通信根据通信的内容可以划分为两种:控制信息的传送与大批量数据传送。

  
4.7.1 进程的通信方式
  
   在单机系统中,进程间通信可分为四种形式:

image007.gif 主从式 ;
  
 image007.gif 会话式;
image007.gif 消息或信箱机制;
image007.gif  共享存储区方式。

主从式(master-servant system)通信系统的主要特点是:

image007.gif a.主进程可自由地使用从进程的资源或数据;
image007.gif b.从进程的动作受主进程的控制;
image007.gif c.主进程和从进程的关系是固定的.
  
   主从式通信系统的典型例子是终端控制进程和终端进程。
  
会话方式(dialogue system) 中,通信进程双方可分别称为使用进程和服务进程。其中,使用进程调用服务进程提供的服务。它们具有如下特点:
   
image007.gif a.使用进程在使用服务进程所提供的服务之前,必须得到服务进程的许可;
    image007.gif b.服务进程根据使用进程的要求提供服务,但对所提供服务的控制由服务进程自身完成。
    image007.gif c.使用进程和服务进程在进行通信时有固定连接关系。
  
   
消息或邮箱机制 则无论接收进程是否已准备好接收消息,发送进程都将把所要发送的消息送入缓冲区或邮箱。这里,消息(message)是用来区别于命令(command)或指令(instruction)等用语的。除了表示所交换的数据传递大量信息之外,消息还具有两互相通信的进程地位平等的意思。
   消息的一般形式为四个部分组成
   
image007.gif 发送进程名
    image007.gif 接收进程名
    image007.gif 数据
    image007.gif 有关数据的操作

        image001.gif
                           图   消息的组成
  
消息或邮箱机制的特点是:
    
image007.gif a.只要存在空缓冲区或邮箱,发送进程就可以发送消息。
    
image007.gif b.与会话系统不同,发送进程相接收进程之间无直接连接关系,接收进程可能在收到某个发送进程发来的消息之后,又转去接收另一个发送进程发来的消息。
    
image007.gif  c.发送进程相接收进程之间存在有用来存放被传送消息的缓冲区或邮箱。
             
image002.gif
                            
图   缓冲区或邮箱通信结构

   
与前面三种方式不同,共享存储区方式不要求数据移动。两个需要互相交换信息的进程通过对同一共享数据区(shared memory)的操作来达到互相通信的目的。这个共享数据区是每个互相通信进程的一个组成部分。
 
   4.7.2 消息缓冲机制


  
消息缓冲机制中所使用的缓冲区为公用缓冲区,使用消息缓冲机制传送数据时,两通信进程必须满足如下条件:

   
image007.gif a.在发送进程把消息写入缓冲区和把缓冲区挂入消息队列时,应禁止其它进程对该缓冲区消息队列的访问。否则,将引起消息队列的混乱。同理,当接收进程正从消息队列中取消息缓冲时,也应禁止其它进程对该队列的访问。
   
   
image007.gif
 b.当缓冲区中无消息存在时,接收进程不能接收到任何消息 。

   
设公用倍号量mutex为控制对缓冲区访问的互斥信号量,其初值为1。设SM为接收进程的私用信号量,表示等待接收的消息个数,其初值为0。设发送进程调用过程:send(m)将消息m送往缓冲区,接收进程调用过程Receive(m)将消息m从缓冲区读往自己的数据区,则Send(m)和Receive(n)可分别描述为:

   Send(m):
           begin
           向系统申请一个消息缓冲区
           P(mutex)
           将发送区消息m送入新申请的消息缓冲区
           把消息缓冲区挂入接收进程的稍息队列
           V(mutex)
           V(SM)
           end

Receive(n):

        begin
            P(SM)
           P(mutex)
           摘下消息队列中的消息n
           将消息n从缓冲区复制到接收区
           释放缓冲区
           V(mutex)
           End


 
  4.7.3 邮箱通信


    邮箱通信
就是由发送进程申请建立一与接收进程链接的邮箱。发送进程把消息送往邮箱,接收进程从邮箱中取出消息,从而完成进程间信息交换。
  
    邮箱由邮箱头和邮箱体组成。其中邮箱头描述邮箱名称、邮箱大小、邮箱方向以及拥有该邮箱的进程名等。邮箱体主要用来存放消息。

 

            image003.gif

                               图   邮箱通信结构
对于只有一发送进程和一接收进程使用的邮箱,进程间通信应满足如下条件

     image007.gif a.发送进程发送消息时,邮箱中至少要有一个空格能存放该消息。

     image007.gif b.接收进程接收消息时,邮箱中至少要有一个消息存在。


 
   设发送进程调用过程deposit(m)将消息发送到邮箱,接收进程调用过程remove(m)将消息m从邮箱中取出。另外,为了记录邮箱中空格个数和消息个数,信号量fromnum为发送进程的私用信号量,信号量mesnum为接收进程的私用信号量。fromnum的初值为信箱的空格数n.mesnum的初值为0。则deposit(m)和remove(m)可描述如下:

deposit(m):

begin local x

P(fromnum)
选择空格x
将消息m放入空格x中
置格x的标志为满
V(mesnum)

end

remove(m):

begin local x

P(mesnum)
选择满格x
把满格x中的消息取出放m中
置格x标志为空
V(formnum)

end

显然,调用过程deposit(m)的进程与调用过程remove(m)的进程之间存在着同步制约关系而不是互斥制约关系。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12315270/viewspace-620453/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/12315270/viewspace-620453/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值