进程间通信方式

  • @[TOC](进程间通信方式)
    • 1、管道
    • 2、消息队列
    • 3、共享内存
    • 4、信号量
    • 5、Socket

1、管道

1.1 匿名管道

主要用于有亲缘关系的进程间通信

我们先来看一条Linux语句:

test1 | grep 8080

如果你还没忘记Linux命名,那一定知道 “ | ”的意思,其实它就是管道的意思,他的作用就是把前一个命令的输出作为后一条命令的输入。

以上代码其实就是把test1的输出作为grep 8080这条命令的输入,这里的“ | ”其实是一个匿名管道,只能用于有亲缘关系进程的通信。

如果两个进程需要通信的话就得创建两个管道。因为这种通信方式是单向的以下是关于匿名管道的实例:

在程序中,我们创建了一个管道,父进程关闭了写通道,子进程关闭读通道,子进程向管道写入字符串,父进程向管道读取字符串并输出。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#define MAX_LEN 128
int main(void)
{/*0为读,1为写*/int fd[2] = {0}; //描述符pid_t pid = 0;char line[MAX_LEN] = {0};int n = 0;/*创建管道,需要传入两个文件描述符*/if(pipe(fd) < 0){perror("create pipe failed\n");return -1;}/*fork子进程*/if((pid = fork()) < 0){perror("fork failed\n");return -1;}/*父进程*/else if(pid > 0){/*关闭管道的写描述符*/close(fd[1]);/*从管道读取数据*/n = read(fd[0],line,MAX_LEN);printf("read %d bytes from pipe :%s\n",n,line);}/*子进程*/else{/*关闭管道的读描述符*/close(fd[0]);/*向管道写入数据*/write(fd[1],"test",sizeof("test"));}return 0;
}

1.2、命名管道

命名管道可以用于任意进程间通信。

以下是创建一个命名管道等方法:

mkfifo test

这条命令创建了一个名为test的管道,接下来我们用一个进程向这个管道写数据,然后另一个进程将写入的数据读出:

echo “this is a pipe” >test

如果该管道的数据没有被读出,那它将一直等待,直到有其他进程经数据读出:

cat < test  //读数据

只有数据被其他进程读出,上一条写数据的才算结束。
这里也体现出管道的缺点——效率低下,我给你传数据,但是只有你把数据拿走了,我才能返回,这样是很慢的,不适合频繁通信的进程。但同时也有一个优点,那就是可以保证你是真的拿到了我的数据。

以下是一个关于命名管道完整代码的实例:

我们首先创建一个命名管道,如果成功,则关闭他的读端,向里面写入数据。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#define FIFO "/tmp/fifo"
#define MAX_LEN 128
int main(void)
{int writeFd;char line[MAX_LEN] = {0};if(mkfifo(FIFO,S_IRUSR|S_IWUSR) < 0 && (errno != EEXIST)){perror("make fifo failed:");return -1;}/*关闭管道的读描述符*/writeFd = open(FIFO,O_WRONLY,0);/*向管道写入数据*/write(writeFd,"www.yanbinghu.com",sizeof("www.yanbinghu.com"));close(writeFd);return 0;
}

然后再新的终端打开一个刚才创建的命名管道,从里面读取数据:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include<fcntl.h>
#define FIFO "/tmp/fifo"
#define MAX_LEN 128
int main(void)
{int readFd,n;char line[MAX_LEN] = {0};/*打开FIFO,这里打开可能失败,应该要对返回值处理*/readFd = open(FIFO,O_RDONLY,0);/*从FIFO读取数据*/n = read(readFd,line,MAX_LEN);printf("read %d bytes from pipe :%s\n",n,line);close(readFd);/*删除FIFO*/unlink(FIFO);return 0;
}

然后运行写进程和读进程,这样两个没有亲缘关系的进程就可以通过匿名管道进行通信了。

总结:

  • 半双工,即就是不能够同时在两个方向上传输数据,有的系统可能支持全双工。
  • 匿名管道只能用于有亲缘关系的进程进行通信
  • 命名管道可以用于任意进程间通信

2、消息队列

学习了以上管道我们知道,a向b 写数据,只有b把数据读出,a才能返回,那我们能不能不等待,我把数据传给你,然后我立即返回呢?

其实是可以的,消息队列就可以解决这样的问题,a只要把给b的数据放进消息队列里面就可以了,b要用数据直接从消息队列取出。

  • 缺点:如果a给b发送的数据过大,并且通信频繁,那消息队列就不合适了,因为数据过大,a发送数据的时间长,b去拷贝数据花费时间也长,效率就会变低。
  • 优点:管道一旦相关进程退出,那里面的数据也就没有了,但消息队列不一样,一个进程向里面写入数据后退出,另一个进程仍然可以取数据。

3、共享内存

针对消息队列的缺点,共享内存允许多个进程共享一个给定的存储区,由于他们是共享一块内存数据,减少了内存拷贝的时间,因此速度非常快

但这里我们可能会问:每个进程不是独立的吗?怎么可以共享内存呢?

其实,系统加载一个进程时,分配给进程的内存并不是实际的物理内存,而是虚拟内存空间,我们可以让两个进程各自拿出一块虚拟地址空间来,然后映射到相同的物理内存中,这样虽然两个进程有独立的虚拟地址空间,但有一部分是映射的相同的物理内存,这样就完成了内存共享机制,如下图所示:

缺点:多进程竞争内存,类似于我们平常说的线程安全。

4、信号量

一句话概括:信号量的本质就是一个计数器,用来实现进程之间的同步与互斥。

例如信号量的初始值为1,然后a进程来访问共享内存的时候,我们把信号量的值设为0,然后b进程来访问共享内存的时候,看到信号量的值为0,就知道已经有人来访问内存了,那b就访问不了了。所以说信号量也是进程间的一种通信方式。

5、Socket

以上我们所说的管道,消息队列,共享内存,信号量都是同一主机之间的通信,那两个相隔几千里的进程怎么进行通信呢?

答案就是Socket,例如平时我们通过浏览器发起一个http请求,然后服务器给你返回对应的数据,这种就是采用了Socket的通信方式,也就是说:它能用于不同计算机之间的不同进程间的通信。

总结

  • 对于管道:速度慢,最后一个引用它的进程终止的时候,留在管道的数据也会被删除。匿名管道用于有亲缘关系的进程,命名管道用于任意键进程通信。半双工通信,一个写数据,一个读数据,只能是单向的。
  • 消息队列:内核中的优先级队列,多个进程通过向同一个队列中放置队列结点或者获取节点实现通信
  • 共享内存:各个进程通过映射相同的物理地址实现通信,减少了内存拷贝时间。但是要注意多进程通信的安全
  • 信号量:通过计数器来检测内存的访问情况,如果有进程访问内存,计数变为0,没有进程访问,计数变为1.计数只有0/1两种状态。
  • Socket用于不同计算机之间不同进程的通信,是目前应用最广泛的进程间通信方式。

【Linux】 ——进程间通信方式优缺点比较相关推荐

  1. [【转载】 linux进程间通信方式

    目录 目录 进程通信的目的 Linux 进程间通信(IPC)的发展 linux使用的进程间通信方式 管道( pipe ) 信号量( semophore ) 消息队列( message queue ) ...

  2. dat关闭某进程_超详细解析!工程师必会的Linux进程间通信方式和原理

    ▍进程的概念 · 进程是操作系统的概念,每当我们执行一个程序时,对于操作系统来讲就创建了一个进程,在这个过程中,伴随着资源的分配和释放.可以认为进程是一个程序的一次执行过程. ▍进程通信的概念 · 进 ...

  3. linux 进程间通信方式

    1. 用户态和内核态进程通信 1)系统调用,最常用, 比如针对IO,有linux同步io接口(libaio最终也是调用linux同步io系统接口),linux aio ,linux io_uring ...

  4. linux进程间通信方式及比较

    进程间的通信方式: 1.管道(pipe)及有名管道(named pipe): 管道可用于具有亲缘关系进程间的通信,有名管道除了具有管道所具有的功能外,它还允许无亲缘关系进程间的通信. 2.信号(sig ...

  5. <Linux进程间通信方式-详细总结>

    文章目录 1.进程间通信(IPC) 2.进程间通信方式一:管道 2.进程间通信方式二:共享内存 3.进程间通信方式三:消息队列 4.进程间通信方式四:信号量 1.进程间通信(IPC) 1.进程间通信方 ...

  6. Linux进程间通信方式

    1. 管道:简单 实现原理: 操作系统的内核借助环形队列机制,使用内核缓冲区实现.特质: 1. 伪文件2. 管道中的数据只能一次读取.3. 数据在管道中,只能单向流动.局限性:1. 自己写,不能自己读 ...

  7. Linux进程间通信方式--本地socket

    先上一个代码 服务端: [cpp] view plaincopy //s_unix.c #include <stdio.h> #include <sys/types.h> #i ...

  8. Linux进程间通信(五)——进程间通信

    一.进程间通信简介 Linux的进程通信方式基本上是从Unix平台上的进程通信方式继承而来的.在Unix发展过程中,贝尔实验室和BSD(加州大学伯克利分校的伯克利软件发布中心)是Unix发展的主要贡献 ...

  9. Linux应用开发【第四章】Linux进程间通信应用开发

    文章目录 4 Linux进程间通信应用开发 4.1 初识进程 4.1.1 进程的概念 4.1.1.1 程序 4.1.1.2 进程 4.1.1.3 进程和程序的联系 4.1.1.4 进程和程序的区别 4 ...

最新文章

  1. OSChina 周三乱弹 —— 一起 High High High!
  2. 设计模式10——flyweight模式
  3. bit_length
  4. Google BERT模型提取句子Token特征
  5. 副连长是什么级别_“上尉副连长”和“中尉连长”谁的级别高 别再傻傻不知道!...
  6. SAP APF modeler过滤器的设计原理
  7. mysql 常用字符串操作
  8. 算法工程师面试备战笔记7_数据清洗与特征处理
  9. Android CheckBox 实战
  10. 《ARM Cortex-M3权威指南》--语句摘要
  11. 外设驱动库开发笔记41:ADS1256 ADC驱动
  12. cups ipp oracle,Linux打印系统CUPS原理分析
  13. HTML期末学生作业~html+css+javascript仿猫眼电影在线网站[毕业设计]
  14. 【数据科学家学习小组】之统计学(第二期)第一周(20191028-20191103)-momi
  15. excel怎么算复购率(EXCEL怎么算平均分)
  16. 推荐几个高质量图片网站,再也不怕没图装X了 1
  17. 自学Java笔记2 2021-3-28更
  18. Weakly Supervised Video Salient Object Detection
  19. 2016世界人工智能大会 AI领袖共启智能+新纪元
  20. 诺奖得主公司CAR-T细胞疗法临床试验现患者死亡,系今年第6例-1

热门文章

  1. 我的世界服务器换披风的网站,minecraft我的世界局域网换皮肤和披风
  2. PyCharm设置书签的设置使用以及pycharm快捷键
  3. 微信小程序的云开发以及与传统开发的比较
  4. [附源码]java毕业设计网上花店系统
  5. java boolean 语法_Java Boolean booleanValue()方法
  6. android浮窗播放器,Android仿优酷视频的悬浮窗播放效果
  7. 饥荒联机版与服务器中断,为什么玩饥荒玩着玩着与服务器断开连接quest; | 手游网游页游攻略大全...
  8. “杠上”拼多多?聚划算加入百亿补贴大战,阿里也焦虑?
  9. 我的世界总说是找不到java_我的世界,我安装了java,但是他说找不到java路径是怎么回事。。。。谁帮我解决下?...
  10. 20200102每日一算法