刚请完婚假,请假期间做了些技术总结,其中一个就是Linux进程间通信方式的总结。

Linux提供了多种进程间通信的方式,列举如下:

  • PIPE(管道)
  • FIFO(先进先出,也称为有名管道)
  • domain_socket(域套接字)
  • XSI-semaphore(XSI信号量)
  • XSI-message_queue(XSI消息队列)
  • XSI-shared_memory(XSI共享内存)
  • POSIX-semaphore(POSIX信号量)
  • mutex(互斥量)

其中semaphore和互斥量虽然是进程或线程间的同步方式,但是同步其实本质上也是通信的一种,所以这里也一并列出来。

PIPE

管道是最古老也是最常用的进程间通信方式,我们在Linux命令行中使用的ls | grep crond就是使用管道将前一个进程的输出重定向为后一个进程的输入。管道主要的缺点是:

  1. 只能用于父子或其它有共同祖先的进程之间;
  2. 是单工通信。

FIFO

为了克服管道只能用于父子进程间的缺点,引入了有名管道,又称为先入先出队列。FIFO的操作方式与普通文件类似,但是必须同时有写端和读端才可操作。

相对于PIPE,FIFO的主要改进是:

  1. 可以用于任意两个进程之间
  2. 可以通过FIFO文件的属性来控制访问权限

Domain Socket

域套接字是一种类似于网络套接字的通信方式,但是专门用于同一台主机的两个进程之间,它是一种双工的通信方式。

XSI Semaphore

XSI是X/Open System Interfaces的缩写,是一种系统接口的标准,它规定了三种通信方式,即semaphore、message queue、shared memory,它们有一致的编程接口。Linux系统上可以使用两种形式的信号量,一种是这里说的XSI_semaphore,还有一种是POSIX_semaphore,后面再解释什么是POSIX_semaphore。

在非必须的情况下,个人不推荐使用XSI进程间通信的方,因为它比较复杂。除了共享内存之外,另外两种XSI进程间通信方式都有其它的替代方法。XSI进程间通信的大致流程如下:

  1. 两个进程获取一个key
  2. 两个进程使用这个key来获取进程间通信的ID
  3. 两个进程进行进程间通信
  4. 其中一个进程释放进程间通信的ID

最麻烦的地方在于,进程间通信的ID不会随着进程结束自动释放,必须要手动释放。

信号量用于保护不同进程或线程对于有限资源的访问,在进程访问资源前,需要获取信号量,访问结束后释放信号量。当信号量当前值等于0时,获取信号量的进程必须等待,直到有其它进程释放信号量。

XSI Message Queue

消息队列是另一种XSI进程间通信方式,通过两个进程读写同一个内核消息队列来实现进程间通信。

XSI Shared Memory

共享内存是一种最高效的进程间通信方式,直接将一片内存同时映射到两个进程中,然后两个进程读写这片内存即可实现进程间通信。它的代价就是要自己进程同步操作防止出现数据不一致的情况。

POSIX Semaphore

相对于XSI Semaphore,POSIX Semaphore要容易使用的多。

Mutex

一般来说mutex只用于线程间同步,但是通过将一个mutex变量映射到两个不同进程的地址空间中,并设置mutex的进程间共享的属性,也可以用于进程间通信,不过比较麻烦就是啦。如果对于mutex有特殊的爱好,也可以使用的哦。

代码

所有的代码已上传到https://github.com/clpsz/linux-ipcs。虽然每个目录都只有一个main函数,但是代码中使用fork创建了两个进程,不过除了PIPE之外,其它的进程间通信方式并不限于父子进程之间,使用fork只是为了方便测试。

Linux进程间通信总结的更多相关文章

  1. Linux进程间通信(一): 信号 signal()、sigaction()

    一.什么是信号 用过Windows的我们都知道,当我们无法正常结束一个程序时,可以用任务管理器强制结束这个进程,但这其实是怎么实现的呢?同样的功能在Linux上是通过生成信号和捕获信号来实现的,运行中 ...

  2. Linux进程间通信(二):信号集函数 sigemptyset()、sigprocmask()、sigpending()、sigsuspend()

    我们已经知道,我们可以通过信号来终止进程,也可以通过信号来在进程间进行通信,程序也可以通过指定信号的关联处理函数来改变信号的默认处理方式,也可以屏蔽某些信号,使其不能传递给进程.那么我们应该如何设定我 ...

  3. Linux进程间通信(三):匿名管道 popen()、pclose()、pipe()、close()、dup()、dup2()

    在前面,介绍了一种进程间的通信方式:使用信号,我们创建通知事件,并通过它引起响应,但传递的信息只是一个信号值.这里将介绍另一种进程间通信的方式——匿名管道,通过它进程间可以交换更多有用的数据. 一.什 ...

  4. Linux进程间通信(四):命名管道 mkfifo()、open()、read()、close()

    在前一篇文章—— Linux进程间通信 -- 使用匿名管道 中,我们看到了如何使用匿名管道来在进程之间传递数据,同时也看到了这个方式的一个缺陷,就是这些进程都由一个共同的祖先进程启动,这给我们在不相关 ...

  5. Linux进程间通信(五):信号量 semget()、semop()、semctl()

    这篇文章将讲述别一种进程间通信的机制——信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信 -- 信号.下面 ...

  6. Linux进程间通信(六):共享内存 shmget()、shmat()、shmdt()、shmctl()

    下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式 ...

  7. Linux进程间通信(七):消息队列 msgget()、msgsend()、msgrcv()、msgctl()

    下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信 -- 使用命名管道 一.什么是消息队列 消息队列提 ...

  8. Linux进程间通信(九):数据报套接字 socket()、bind()、sendto()、recvfrom()、close()

    前一篇文章,Linux进程间通信——使用流套接字介绍了一些有关socket(套接字)的一些基本内容,并讲解了流套接字的使用,这篇文章将会给大家讲讲,数据报套接字的使用. 一.简单回顾——什么是数据报套 ...

  9. [转]Linux进程间通信——使用消息队列

    点击此处阅读原文 另收藏作者ljianhui的专栏初学Linux 下面来说说如何使用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linu ...

  10. Linux 进程间通信(二) 管道

    Linux 进程间通信-管道 进程是一个独立的资源分配单位,不同进程之间的资源是相互独立的,没有关联,不能在一个进程中直接访问另一个进程中的资源.但是,进程不是孤立的,不同的进程之间需要信息的交换以及 ...

随机推荐

  1. python初学笔记(二)

    注释: 任何时候,我们都可以给程序加上注释.注释是用来说明代码的,给自己或别人看,而程序运行的时候,Python解释器会直接忽略掉注释,所以,有没有注释不影响程序的执行结果,但是影响到别人能不能看懂你 ...

  2. linux shell 札记

    shell 数组 数组索引: 单个元素索引: ${array[n]} 全部元素:   ${array[*]}  或者  ${array[@]} 部分索引: ${array[2:]} 数组所有元素统一加 ...

  3. Task和backStack(本篇章核心)

     对Task和backStack的认识过程 1.由demo测试得到的关系图: 1.一个task中可以有多个app的Activity, 由于一个app可以对应一个或多个process, 2.所以一个ta ...

  4. MBG 相关资源链接

    MyBatis Generator(MBG)相关资源链接 http://mbg.cndocs.tk/quickstart.html http://www.mybatis.tk/ http://git. ...

  5. java 操作配置文件 .properties

    package com.dms.common; import java.io.File; import java.io.FileInputStream; import java.io.FileNotF ...

  6. uva 10129 poj 1386 hdu 1116 zoj 2016 play on words

    //本来是想练一下欧拉回路的,结果紫书上那题是大水题!!!!! 题意:给出n个单词,是否可以把单词排列成每个单词的第一个字母和上一个单词的最后一个字母相同 解:欧拉通路存在=底图联通+初度!=入度的点 ...

  7. POJ1008

    2014-08-22 题意: (有中文版题目..)  就是两种历法的转换 思路: 把两种历法的细节了解了就很简单了 Haab历法一年365,Tzolkin一年260天 先求出总天数sumDay,然后s ...

  8. linux 磁盘空间扩容 vg(+pv) lv(+空间) lv(缩减磁盘空间)

    preFace APP scenario description: 当你未能合理的规划存储时,在后期的维护工作中可能会涉及的存储的 再规划(eg,某一个 or 数个App 对某一个lv 即挂载点写Bi ...

  9. NSFileHandle编写json数据格式

    代码如下: + (void)writeToFile:(NSDictionary *)params filePath:(NSString *)path { NSData *jsonData = [sel ...

  10. 调用父类Controller错误

    在写一个控制器的时候,要特别注意本类继承的父类.不要继承错了.如图: ,这样就会一直是显示父类的控制器,而不是显示本类的控制器视图. 应该改为: 这些都是平时遇到的一些小问题,留着提醒自己.