刚请完婚假,请假期间做了些技术总结,其中一个就是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. C#文本文件或其他文件新内容追加

    以txt文本为例,以下代码实现a.txt文件中追加内容 FileStream mystream = new FileStream("C:\\a.txt", FileMode.Ope ...

  2. Drools

    http://www.infoq.com/news/2009/06/drools-5.0-release http://www.javacodegeeks.com/2014/03/event-proc ...

  3. 如何在 静态编译的QT 5.5.1 中 使用数据库插件连接 ODBC(调用静态插件)

    前段时间由于工作的关系,需要编写一个将数据插入到 Sql server 2012 的桌面软件. 由于之前使用的是MFC,偶然间接触到了Qt后,被它的简洁惊艳到了,于是便毅然而然的转投到了Qt的怀抱,哈 ...

  4. 【译】浅谈微软OneNote的自动化测试工具

    当我们向人们介绍OneNote的自动化时,有一个问题被相当频繁地提到,担忧我们的自动化框架中UI层面测试偏少. 我不喜欢基于UI的自动化.我知道在市场上有许多的自动化系统都是基于UI的自动化(点击按钮 ...

  5. centos 6.7 perl 5.22 安装DBD 需要使用老的perl版本

    zjzc01:/usr/bin# mv perl.bak perlold zjzc01:/usr/bin# cd zjzc01:/root# cd DBD-Oracle-1.36 zjzc01:/ro ...

  6. C++默认参数与函数重载 注意事项

    一.默认参数在C++中,可以为参数指定默认值.在函数调用时没有指定与形参相对应的实参时, 就自动使用默认参数. 默认参数的语法与使用:(1)在函数声明或定义时,直接对参数赋值.这就是默认参数:(2)在 ...

  7. C++中的句柄类

    初次在<C++ Primer>看到句柄,不是特别理解.在搜索相关资料后,终于有了点头绪. 首先明白句柄要解决什么问题.参考文章<C++ 沉思录>阅读笔记——代理类 场景: 我们 ...

  8. nova的wsgi介绍【WIP】

    有关openstack的所有的帖子. https://www.ustack.com/blog/openstack_hacker/#Nova_Workflow 网上已经很多的分析文章了: http:// ...

  9. iOS获取手机当前的网络状态

    获取iOS网络状态,目前有两个办法. 1.通过监听手机状态栏的信息. 2.通过使用官方提供的类Reachability. 一.通过手机监听手机状态栏的信息 好处: 1.可以通过苹果的审核上架AppSt ...

  10. Java面试题之四

     十六.运行时异常与一般异常有何异同 Java提供了两类主要的异常:runtime exception和checked exception. 1.checked exception:这种异常也就是我们 ...