前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >进程之间的通信方式「建议收藏」

进程之间的通信方式「建议收藏」

作者头像
全栈程序员站长
发布2022-11-10 15:42:42
5990
发布2022-11-10 15:42:42
举报
文章被收录于专栏:全栈程序员必看

进程间通信方式一般有以下几种: 1、管道,匿名管道,命名管道 2、信号 3、信号量 4、消息队列 5、共享内存 6、socket

管道

  • 管道数据只能单向流动,所以如果要实现双向通信,就要创建2个管道
  • 管道分为匿名管道和命名管道
    • 匿名管道只能在父子进程关系之间使用
    • 命名管道,可以在不关联的两个进程之间使用,因为它创建了一个类型为管道的设备文件,使用这个设备文件就可以通信。
  • 管道只能承载无格式的字节流

信号

信号是进程之间唯一的异步通信机制,信号的主要来源主要有硬件来源(入键盘操作ctrl + C) 和软件来源(如kill命令),信号传递的信息比较少,主要用于通知进程某个时间已经发生。比如利用kill pid,可以让系统优雅停机。

信号量

信号量是一个计数器,可以用来控制多个进程对资源的访问,通常作为一种锁机制,防止某个进程正在访问共享资源,其他进程也访问资源

消息队列

消息队列克服了信号传递信息少、管道只能承载无格式的字节流,消息到了就放进去,需要的时候去取。与命名管道相比:消息队列的优势在于,它独立于发送和接收线程,消除了在同步命名管道的打开和关闭时可能产生的一些困难。

共享内存

共享内存就是映射一段能被进程之间共享的内存,这段内存由一个进程创建,但是多个进程都可以共享访问,是最快的一种进程间通信的方式(不需要从用户态到内核态的切换),它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。

socket

socket套接字,不仅仅可以用于本地进程通信,还可以用于不通主机进程之间的通信。

关于管道:

匿名管道的创建,需要通过下面这个系统调用: intpipe(int fd[2]) 这里表示创建一个匿名管道,并返回了两个描述符,一个是管道的读取端描述符 fd[0],另一个是管道的写入端描述符 fd[1]。注意,这个匿名管道是特殊的文件,只存在于内存,不存于文件系统中。

在这里插入图片描述
在这里插入图片描述

其实,所谓的管道,就是内核里面的一串缓存。从管道的一段写入的数据,实际上是缓存在内核中的,另一端读取,也就是从内核中读取这段数据。另外,管道传输的数据是无格式的流且大小受限。 看到这,你可能会有疑问了,这两个描述符都是在一个进程里面,并没有起到进程间通信的作用,怎么样才能使得管道是跨过两个进程的呢? 我们可以使用 fork 创建子进程,创建的子进程会复制父进程的文件描述符,这样就做到了两个进程各有两个「 fd[0] 与 fd[1]」,两个进程就可以通过各自的 fd 写入和读取同一个管道文件实现跨进程通信了。

在这里插入图片描述
在这里插入图片描述

管道只能一端写入,另一端读出,所以上面这种模式容易造成混乱,因为父进程和子进程都可以同时写入,也都可以读出。那么,为了避免这种情况,通常的做法是: 父进程关闭读取的 fd[0],只保留写入的 fd[1]; 子进程关闭写入的 fd[1],只保留读取的 fd[0];

在这里插入图片描述
在这里插入图片描述

所以说如果需要双向通信,则应该创建两个管道。 到这里,我们仅仅解析了使用管道进行父进程与子进程之间的通信,但是在我们 shell 里面并不是这样的。 在 shell 里面执行 A | B命令的时候,A 进程和 B 进程都是 shell 创建出来的子进程,A 和 B 之间不存在父子关系,它俩的父进程都是 shell。

在这里插入图片描述
在这里插入图片描述

所以说,在 shell 里通过「|」匿名管道将多个命令连接在一起,实际上也就是创建了多个子进程,那么在我们编写 shell 脚本时,能使用一个管道搞定的事情,就不要多用一个管道,这样可以减少创建子进程的系统开销。

我们可以得知,对于匿名管道,它的通信范围是存在父子关系的进程。因为管道没有实体,也就是没有管道文件,只能通过 fork 来复制父进程 fd 文件描述符,来达到通信的目的。

另外,对于命名管道,它可以在不相关的进程间也能相互通信。因为命令管道,提前创建了一个类型为管道的设备文件,在进程里只要使用这个设备文件,就可以相互通信。

不管是匿名管道还是命名管道,进程写入的数据都是缓存在内核中,另一个进程读取数据时候自然也是从内核中获取,同时通信数据都遵循先进先出原则,不支持 lseek 之类的文件定位操作。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/183208.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年10月11日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 管道
  • 信号
  • 信号量
  • 消息队列
  • 共享内存
  • socket
  • 关于管道:
相关产品与服务
消息队列 CMQ 版
消息队列 CMQ 版(TDMQ for CMQ,简称 TDMQ CMQ 版)是一款分布式高可用的消息队列服务,它能够提供可靠的,基于消息的异步通信机制,能够将分布式部署的不同应用(或同一应用的不同组件)中的信息传递,存储在可靠有效的 CMQ 队列中,防止消息丢失。TDMQ CMQ 版支持多进程同时读写,收发互不干扰,无需各应用或组件始终处于运行状态。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档