在众多大佬肩膀之上——浅谈进程间的通信方式(一)

1、进程间通信概述
fork函数和exec函数传送打开文件或者打开文件系统只是单方面的单机pc,是残缺的并不能实现进程间的相互通信,进程之间的相互通信的其他技术——IPC。
(InterProcess Communication)
2、管道通信原理
IPC的方式通常有管道(包括无名管道和命名管道)、消息队列、信号量、共享存储、Socket、Streams等。其中Socket和Streams支持不通知主机上的两个进程IPC。
管道中的数据,读走就没了。

一、无名管道

3、无名管道 pipe()。
特点:
1、它是半双工的(即数据只能在一个方向上流动) ,具有固定的读端和写端。
2、它只能用于具有亲缘关系的进程之间的通信(也是父子进程或者兄弟进程之间)。
3、它可以看成是一种特殊的文件,对于它的读写也可以使用普遍的read, write等函数,但是它不是普遍的文件,并不属于其他1文件系统,并且只存在于内存中。
在这里插入图片描述
当一个管道建立时,它会创建两个文件描述符:fd[0]为读而打开,fd[1]为写而打开。如下图所示。
在这里插入图片描述
要关闭管道只需将这两个文件描述符关闭即可。

单个进程中的管道几乎没有任何用处。所以,通常调用 pipe 的进程接着调用 fork,这样就创建了父进程与子进程之间的 IPC 通道。如下图所示。
在这里插入图片描述

编程实例
在这里插入图片描述
二、命名管道

5、创建命名管道 FIFO
FIFO,也称为命名管道,它是一种文件类型。
依赖于文件系统,像普通文件一样具有磁盘路径,文件权限和其他属性,所有程序都可以通过path找到有名管道。
1、特点
a、FIFO可以在无关的进程之间交换数据,与无名管道不同。
b、FIFO有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中。
2、原型
在这里插入图片描述
其中的 mode 参数与open函数中的 mode 相同。一旦创建了一个 FIFO,就可以用一般的文件I/O函数操作它。
两个进程,中途退出了一个进程,未退出的一端如果是写操作的话,返回sigpipe信号
未退出的一端如果是阻塞读操作的话,该读操作不会继续阻塞,直接返回
0
**
当 open 一个FIFO时,是否设置非阻塞标志(O_NONBLOCK)的区别:
a、 若没有指定O_NONBLOCK(默认),只读 open 要阻塞到某个其他进程为写而打开此 FIFO。类似的,只写 open要阻塞到某个其他进程为读而打开它。
b、 若指定了O_NONBLOCK,则只读 open 立即返回。而只写 open 将出错返回 -1 如果没有进程已经为读而打开该FIFO,其errno置ENXIO。
3、例子
FIFO的通信方式类似于在进程中使用文件来传输数据,只不过FIFO类型文件同时具有管道的特性。在数据读出时,FIFO管道中同时清除数据,并且“先进先出”。下面的例子演示了使用 FIFO 进行 IPC 的过程:
write_fifo
在这里插入图片描述
read_fifo
在这里插入图片描述
上述例子可以扩展成 客户进程—服务器进程 通信的实例,write_fifo的作用类似于客户端,可以打开多个客户端向一个服务器发送请求信息,read_fifo类似于服务器,它适时监控着FIFO的读端,当有数据时,读出并进行处理,但是有一个关键的问题是,每一个客户端必须预先知道服务器提供的FIFO接口,下图显示了这种安排:
在这里插入图片描述
6、system v ipc
ipcs

key:通信双方约定好的KEY值,32位的整形数据
id :系统会为IPC分配一个唯一的ID,通信双方都需要知道ID才能使用当前IPC方法,创建者会返回当前ID值,
在这里插入图片描述
对象
拥有者及权限对象

在这里插入图片描述

三、消息队列

7、消息队列
消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。
1、特点
**a、**消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。
**b、**消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。
**c、**消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取。
2、原型
对象:
struct msqid_ds
在这里插入图片描述
在这里插入图片描述
优点和缺点
优点:

  1. 消息队列是两个不相关进程之间传递数据的有效渠道.
  2. 与命名管道相比,具有的优势是:
    独立于发送以及接收进程而存在;
    消除命名管道的打开以及关闭而存在的困难;
    可以提前查看紧急信息;
    避免命名管道的同步以及阻塞问题;
    缺点:
    与命名管道一样,每个数据块都有一个最大长度限制;
    系统中所有队列包含的全部数据块长度也有一个上限;

创建对象:
int msgget(key_t key, int msgflg)

在这里插入图片描述
key_t key
int msgflg 确定消息队列的访问权限,

在这里插入图片描述
设置对象:
在这里插入图片描述
使用对象:
发送

在这里插入图片描述
接收
在这里插入图片描述
在这里插入图片描述
在以下两种情况下,msgget将创建一个新的消息队列:

如果没有与键值key相对应的消息队列,并且flag中包含了IPC_CREAT标志位。
key参数为IPC_PRIVATE。
函数msgrcv在读取消息队列时,type参数有下面几种情况:
type == 0,返回队列中的第一个消息;
type > 0,返回队列中消息类型为 type 的第一个消息;
type < 0,返回队列中消息类型值小于或等于 type 绝对值的消息,如果有多个,则取类型值最小的消息。
可以看出,type值非 0 时用于以非先进先出次序读消息。也可以把 type 看做优先级的权值。(其他的参数解释,请自行Google之)
3、例子
下面写了一个简单的使用消息队列进行IPC的例子,服务端程序一直在等待特定类型的消息,当收到该类型的消息以后,发送另一种特定类型的消息作为反馈,客户端读取该反馈并打印出来。
demoMsgrcv.c
在这里插入图片描述
demoMsgsnd.c
在这里插入图片描述
8、键值生成及消息队列移除
ftok 系统IPC键值的格式转换函数
系统建立IPC通讯(消息队列、信号量和共享内存)时必须指定一个ID值,通常情况下,该ID值通过ftok函数得到。
查询文件索引节点号 ls -i
(下图来源于百度百科)
在这里插入图片描述
msgctl (对消息队列的操作) cmd:
IPC_STAT IPC_INFO
IPC_SET IPC_RMID
IPC_RMID:把消息队列的链表从内核中移除

参考博文:
https://blog.csdn.net/weixin_45309916/article/details/107743249
https://blog.csdn.net/Qxxchampion/article/details/106176535?ops_request_misc=&request_id=&biz_id=102&utm_term=%E8%BF%9B%E7%A8%8B%E9%97%B4%E7%9A%84%E4%BA%94%E7%A7%8D%E9%80%9A%E4%BF%A1%E6%96%B9%E5%BC%8F%E4%BB%8B%E7%BB%8D&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-1-106176535.first_rank_v2_pc_rank_v29

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值