进程间通讯的7种方式

2023-11-10

1、常见的通信方式

  1. 管道pipe:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
  2. 命名管道FIFO:有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
  3. 消息队列MessageQueue:消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
  4. 共享存储SharedMemory:共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。
  5. 信号量Semaphore:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
  6. 套接字Socket:套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。
  7. 信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

2、按通信类型区分

  1. 共享存储器系统
    1.基于共享数据结构的通信方式
    (仅适用于传递相对少量的数据,通信效率低,属于低级通信)
    2.基于共享存储区的通信方式
  2. 管道通信系统
    管道是指用于连接一个读进程和一个写进程以实现它们之间通信的一个共享文件(pipe文件)
    管道机制需要提供一下几点的协调能力
    1.互斥,即当一个进程正在对pipe执行读/写操作时,其它进程必须等待
    2.同步,当一个进程将一定数量的数据写入,然后就去睡眠等待,直到读进程将数据取走,再去唤醒。读进程与之类似
    3.确定对方是否存在
  3. 消息传递系统
    1.直接通信方式
    发送进程利用OS所提供的发送原语直接把消息发给目标进程
    2.间接通信方式
    发送和接收进程都通过共享实体(邮箱)的方式进行消息的发送和接收
  4. 客户机服务器系统
    1.套接字 – 通信标识型的数据结构是进程通信和网络通信的基本构件
    基于文件型的 (当通信进程都在同一台服务器中)其原理类似于管道
    基于网络型的(非对称方式通信,发送者需要提供接收者命名。通信双方的进程运行在不同主机环境下被分配了一对套接字,一个属于发送进程,一个属于接收进程)
    2.远程过程调用和远程方法调用

3、详解

3.1 管道

管道,通常指无名管道,是 UNIX 系统IPC最古老的形式。

1、特点:
它是半双工的(即数据只能在一个方向上流动),具有固定的读端和写端。

它只能用于具有亲缘关系的进程之间的通信(也是父子进程或者兄弟进程之间)。

它可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write 等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。

管道分为pipe(无名管道)和fifo(命名管道)两种,除了建立、打开、删除的方式不同外,这两种管道几乎是一样的。他们都是通过内核缓冲区实现数据传输。

  • pipe用于相关进程之间的通信,例如父进程和子进程,它通过pipe()系统调用来创建并打开,当最后一个使用它的进程关闭对他的引用时,pipe将自动撤销。
  • FIFO即命名管道,在磁盘上有对应的节点,但没有数据块——换言之,只是拥有一个名字和相应的访问权限,通过mknode()系统调用或者mkfifo()函数来建立的。一旦建立,任何进程都可以通过文件名将其打开和进行读写,而不局限于父子进程,当然前提是进程对FIFO有适当的访问权。当不再被进程使用时,FIFO在内存中释放,但磁盘节点仍然存在。

管道的实质是一个内核缓冲区,进程以先进先出的方式从缓冲区存取数据:管道一端的进程顺序地将进程数据写入缓冲区,另一端的进程则顺序地读取数据,该缓冲区可以看做一个循环队列,读和写的位置都是自动增加的,一个数据只能被读一次,读出以后再缓冲区都不复存在了。当缓冲区读空或者写满时,有一定的规则控制相应的读进程或写进程是否进入等待队列,当空的缓冲区有新数据写入或慢的缓冲区有数据读出时,就唤醒等待队列中的进程继续读写。

在这里插入图片描述

3.2 无名管道

pipe的例子:父进程创建管道,并在管道中写入数据,而子进程从管道读出数据

在这里插入图片描述

3.3 命名管道

和无名管道的主要区别在于,命名管道有一个名字,命名管道的名字对应于一个磁盘索引节点,有了这个文件名,任何进程有相应的权限都可以对它进行访问。

而无名管道却不同,进程只能访问自己或祖先创建的管道,而不能访任意访问已经存在的管道——因为没有名字。

Linux中通过系统调用mknod()或makefifo()来创建一个命名管道。最简单的方式是通过直接使用shell

mkfifo myfifo

等价于

mknod myfifo p

以上命令在当前目录下创建了一个名为myfifo的命名管道。用ls -p命令查看文件的类型时,可以看到命名管道对应的文件名后有一条竖线"|",表示该文件不是普通文件而是命名管道。

使用open()函数通过文件名可以打开已经创建的命名管道,而无名管道不能由open来打开。当一个命名管道不再被任何进程打开时,它没有消失,还可以再次被打开,就像打开一个磁盘文件一样。

可以用删除普通文件的方法将其删除,实际删除的事磁盘上对应的节点信息。

例子:用命名管道实现聊天程序,一个张三端,一个李四端。两个程序都建立两个命名管道,fifo1,fifo2,张三写fifo1,李四读fifo1;李四写fifo2,张三读fifo2。

用select把,管道描述符和stdin假如集合,用select进行阻塞,如果有i/o的时候唤醒进程。(粉红色部分为select部分,黄色部分为命名管道部分)

在这里插入图片描述

在这里插入图片描述

3.4 消息队列

消息队列,就是一个消息的链表,是一系列保存在内核中消息的列表。用户进程可以向消息队列添加消息,也可以向消息队列读取消息。

消息队列与管道通信相比,其优势是对每个消息指定特定的消息类型,接收的时候不需要按照队列次序,而是可以根据自定义条件接收特定类型的消息。

可以把消息看做一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息,对消息队列有读权限的进程可以从消息队列中读取消息。

消息队列的常用函数如下表:

在这里插入图片描述

进程间通过消息队列通信,主要是:创建或打开消息队列,添加消息,读取消息和控制消息队列。

3.5 共享内存

共享内存允许两个或多个进程共享一个给定的存储区,这一段存储区可以被两个或两个以上的进程映射至自身的地址空间中,一个进程写入共享内存的信息,可以被其他使用这个共享内存的进程,通过一个简单的内存读取错做读出,从而实现了进程间的通信。

采用共享内存进行通信的一个主要好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝,对于像管道和消息队里等通信方式,则需要再内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次:一次从输入文件到共享内存区,另一次从共享内存到输出文件。

在这里插入图片描述

一般而言,进程之间在共享内存时,并不总是读写少量数据后就解除映射,有新的通信时在重新建立共享内存区域;而是保持共享区域,直到通信完毕为止,这样,数据内容一直保存在共享内存中,并没有写回文件。共享内存中的内容往往是在解除映射时才写回文件,因此,采用共享内存的通信方式效率非常高。

在这里插入图片描述

共享内存有两种实现方式:1、内存映射 2、共享内存机制

3.6 信号量

信号量(semaphore)与已经介绍过的 IPC 结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。

1、特点
信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。

信号量基于操作系统的 PV 操作,程序对信号量的操作都是原子操作。

每次对信号量的 PV 操作不仅限于对信号量值加 1 或减 1,而且可以加减任意正整数。

支持信号量组。

2、原型
最简单的信号量是只能取 0 和 1 的变量,这也是信号量最常见的一种形式,叫做二值信号量(Binary Semaphore)。而可以取多个正整数的信号量被称为通用信号量。

Linux 下的信号量函数都是在通用的信号量数组上进行操作,而不是在一个单一的二值信号量上进行操作。

#include <sys/sem.h>
// 创建或获取一个信号量组:若成功返回信号量集ID,失败返回-1
int semget(key_t key, int num_sems, int sem_flags);
// 对信号量组进行操作,改变信号量的值:成功返回0,失败返回-1
int semop(int semid, struct sembuf semoparray[], size_t numops);  
// 控制信号量的相关信息
int semctl(int semid, int sem_num, int cmd, ...);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

进程间通讯的7种方式 的相关文章

  • Unity - 微信小游戏

    总参考 Unity WebGL 微信小游戏适配方案 公测 安装与使用 下载 Unity插件 并导入至游戏项目中 版本更新请查看更新日志 请查阅推荐引擎版本 安装时选择WebGL组件 最终选择Unity2021 2 5f1c1InstantG

随机推荐

  • 实战项目:图书管理系统介绍

    本文详细的介绍了实战项目之一的图书管理系统 下载后可以直接使用 也可以直接用于毕业设计 本系统前端使用的框架是vue2 elementUI 后端使用的框架为springboot mybatis maven 数据库使用的是myql数据库 安全
  • 【我不知道的css】巧用flex:0实现上方图片下方文字效果

    我不知道的css 巧用flex 0实现上方图片下方文字效果 要求 代码 原理 要求 要求使用flex布局实现下图所示的效果 容器内部左边为图片和文字 图片在上 文字在下 图片大小不一 文字长度不一 但要求文字根据图片的宽度自动换行 代码 d
  • java mysql教程基于_SpringBoot入门教程(五)Java基于MySQL实现附近的人

    附近的人 这个功能估计都不陌生 与之类似的功能最开始是在各大地图应用上接触过 比如搜附近的电影院 附近的超市等等 然而真正让附近的人火遍大江南北的应该是微信 附近的人 这个功能 记得微信刚出的时候 坊间还有一句 寂寞女聊玩微信 寂寞男人搜附
  • spring security 入门与理解

    1 pom加载
  • seo积分排名系统源码_SEO快速排名系统操作手法以及细节

    SEO快速排名是目前我国SEO行业最热门的话题之一 总之 所有的快速行都可以用两个词来解释 那就是点击 任何行业 包括SEO 都可以使用的原因也是一样的 例如 目前我国有大量的快速排序系统 这种快速排序系统由于百度的雷声算法而受到不同程度的
  • 使用阿里云服务器安装宝塔面板搭建网站教程(图文全流程)

    阿里云服务器安装宝塔面板教程 云服务器吧以阿里云Linux系统云服务器安装宝塔Linux面板为例 先配置云服务器安全组开放宝塔所需端口8888 888 80 443 20和21端口 然后执行安装宝塔面板命令脚本 最后登录宝塔后台安装LNMP
  • 6 款 超好用的 Python 时间库

    开源最前线 ID OpenSourceTop 链接 https opensource com article 18 4 python datetime libraries 写过Python程序的人都知道 Python日期和时间的处理非常繁琐
  • TIDB 详解

    TIDB是什么 TIDB 受谷歌Spanner和F1的论文启发的new sql数据库 这类数据库不仅具有NoSQL对海量数据的存储管理能力 还保持了传统数据库支持ACID和SQL等特性 同类数据库还包括巨杉数据库 TiDB的原理与实现 Ti
  • 嵌入式web服务器Boa的移植

    Boa是一种非常小巧的Web服务器 其可执行代码只有大约60KB左右 作为一种单任务Web服务器 Boa只能依次完成用户的请求 而不会fork出新的进程来处理并发连接请求 但Boa支持CGI 能够为CGI程序fork出一个进程来执行 Boa
  • 考研数据结构--第二章:线性表

    系列索引 2023考研王道数据结构知识梳理 文章目录 1 线性表 1 1 线性表定义 1 2 线性表的特点 1 3 线性表的基本操作 2 顺序表 2 1 顺序表的定义 2 2 顺序表的实现 2 2 1 顺序表的静态分配 2 2 1 1 局限
  • Div点击显示再次点击隐藏

    1 先上效果 这是默认显示的时候 这是再点击隐藏的时候 下方代码贴出 有需要的C V直接浏览器查看
  • 【Unity基础】Input.GetAxis()函数

    根据输入设备 参数分为两类 一 触屏类 1 Mouse X 鼠标沿屏幕X移动时触发 2 Mouse Y 鼠标沿屏幕Y移动时触发 3 Mouse ScrollWheel 鼠标滚轮滚动是触发 二 键盘类 1 Vertical 键盘按上或下键时触
  • windows系统下,如何使用win+R快速打开安装的应用

    windows系统下 如何使用win R快速打开安装的应用 随着工作学习时间的增加 我们的桌面就会出现越来越多的文件和应用快捷方式 使得桌面变得很杂乱 有时候需要打开某个应用的时候就可能需要花费时间来找 那我们如何快速打开我们需要的应用呢
  • Layout的放大和缩小效果例子(ScaleAnimation)

    个Layout从中心放大和缩小的例子 直接上代码 1 ScaleDialog java文件 Java代码 package cn com import android app Activity import android graphics
  • TypeError: ‘function‘ object is not subscriptable

    关于错误 TypeError function object is not subscriptable 错误原因 get dummies函数 写成了
  • https网络编程——如何建立利用根证书(凭证)签发建立中继证书(凭证)详解

    参考 如何建立利用根证书 凭证 签发建立中继证书 凭证 详解 地址 https qingmu blog csdn net article details 108221568 spm 1001 2014 3001 5502 目录 在建立中继之
  • oracle 写入 权限设置,改变用户组文件的读写和执行权限

    网上找来一篇关于linux权限修改方式文章 对于我脑子记性不好的人有非常大的帮助 1 更改档案拥有者 命令 chown cfhvR help version user group file 功能 更改文件或者文件夹的拥有者 参数格式 use
  • c++读写文件

    目录 1 写文件 2 读文件 3 二进制方式写文件 4 3 二进制方式读文件 文件类型分为两种 文本文件 文件以文本的ASCII码形式存储在计算机中 二进制文件 文件以文本的二进制形式存储在计算机中 用户一般不能直接读懂它们 操作文件的三大
  • 小型机 PC服务器 性能,pc服务器小型机

    pc服务器小型机 内容精选 换一换 业务测试完成后或不再需要克隆服务器 您可参考本章节删除克隆服务器 删除克隆服务器后 请到弹性云服务器Console界面检查 使用主机迁移服务迁移Windows系统的源端服务器时 要求目的端服务器的磁盘大小
  • 进程间通讯的7种方式

    1 常见的通信方式 管道pipe 管道是一种半双工的通信方式 数据只能单向流动 而且只能在具有亲缘关系的进程间使用 进程的亲缘关系通常是指父子进程关系 命名管道FIFO 有名管道也是半双工的通信方式 但是它允许无亲缘关系进程间的通信 消息队