[Linux][进程间通信][一][匿名管道][命名管道]详细解读

目录

  • 0.进程间通信?
    • 1.进程间通信目的
    • 2.进程间通信分类
    • 3.进程间通信的本质理解
  • 1.什么是管道?
  • 2.匿名管道
    • 1.认识函数
    • 2.如何让不同的进程,看到同一份资源?
    • 3.用fork来共享管道原理
    • 4.站在文件描述符角度 -- 深刻理解管道
    • 5.站在内核角度 -- 管道本质
    • 6.管道读写规则
    • 7.管道特点
    • 8.使用
  • 3.命名管道
    • 0.为什么有命名管道?
    • 1.创建一个命名管道
    • 2.命名管道原理
    • 3.匿名管道与命名管道的区别
    • 4.命名管道的打开规则
    • 5.思考问题
    • 6.使用 -- 极其简化的代码,只供了解使用流程


0.进程间通信?

1.进程间通信目的

  • 数据传输:一个进程需要将它的数据发送给另一个进程
  • 资源共享:多个进程之间共享同样的资源
  • 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止 时要通知父进程)
  • 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另 一个进程的所有陷入和异常,并能够及时知道它的状态改变

2.进程间通信分类

  • 管道:–> Linux原生能提供
    • 匿名管道pipe
    • 命名管道
  • System V IPC:–> 多进程 --> 单机通信
    • System V 消息队列(不常用)
    • System V 共享内存
    • System V 信号量(不讨论 - 原理)
  • POSIX IPC:–> 多线程 --> 网络通信
    • 消息队列
    • 共享内存
    • 信号量
    • 互斥量
    • 条件变量
    • 读写锁

3.进程间通信的本质理解

  • 进程间通信的前提:让不同的进程看到同一块"内存"(特定的结构组织的)
  • 所谓的进程看到同一块"内存",属于哪一个进程?
    • 不能隶属于任何一个进程,而应该更强调共享

1.什么是管道?

  • 从一个进程连接到另一个进程的一个数据流称为一个"管道"
    • 有入口,有出口
    • 管道都是单向传输内容的
    • 管道中传输的都是"资源"
  • 管道通信背后是进程之间通过管道进行通信
    请添加图片描述

2.匿名管道

1.认识函数

功能创建一匿名管道
函数原型int pipe(int fd[2]);
参数:fd文件描述符数组,其中fd[0]表示读端,fd[1]表示写端
返回值成功返回0,失败返回错误代码

请添加图片描述

2.如何让不同的进程,看到同一份资源?

  • 分别以读写方式打开同一个文件
  • fork()创建子进程
  • 双方进程各自关闭自己不需要的文件描述符
  • 以上能够让具有血缘关系的进程进行进程间通信 --> 常用于父子进程

3.用fork来共享管道原理

请添加图片描述

4.站在文件描述符角度 – 深刻理解管道

请添加图片描述

5.站在内核角度 – 管道本质

  • 看待管道,就如同看待文件一样!管道的使用和文件一致
    请添加图片描述

6.管道读写规则

  • 当没有数据可读时:
    • O_NONBLOCK disable:read调用阻塞,即进程暂停执行,一直等到有数据来到为止
    • O_NONBLOCK enable:read调用返回-1,errno值为EAGAIN
  • 当管道满的时候:
    • O_NONBLOCK disable: write调用阻塞,直到有进程读走数据
    • O_NONBLOCK enable:调用返回-1,errno值为EAGAIN
  • 如果所有管道写端对应的文件描述符被关闭,则read返回0
  • 如果所有管道读端对应的文件描述符被关闭,则write操作会产生信号SIGPIPE,进而可能导致write进程退出
  • 当要写入的数据量不大于PIPE_BUF时,Linux将保证写入的原子性
  • 当要写入的数据量大于PIPE_BUF时,Linux将不再保证写入的原子性
  • 所以有如下情况:
    • 写快,读慢,写满不能再写了
    • 写慢,读快,管道没有数据的时候,读必须等待
    • 写关,读0,标识读到了文件结尾
    • 读关,写继续写,OS终止写进程

7.管道特点

  • 只能用于具有共同祖先的进程(具有亲缘关系的进程)之间进行通信
    • 通常,一个管道由一个进程创建,然后该进程调用fork,此后父、子进程之间就可应用该管道
  • 内核会对管道操作进行**访问控制(**同步与互斥)
  • 管道提供面向流式的通信服务 – 面向字节流
  • 管道是基于文件的,文件的生命周期是随进程的,管道的生命周期是随进程的
    • –> 进程退出,管道释放
  • 管道是单向通信的 --> 半双工通信的一种特殊情况
    • 管道是半双工的,数据只能向一个方向流动
    • 需要双方通信时,需要建立起两个管道
      请添加图片描述

8.使用

int main()
{// 1.创建管道int pipefd[2] = {0};int n = pipe(pipefd);// 2.创建子进程pid_t id = fork();if (id == 0){// child - read// 3.构建单向通信的信道// 3.1 关闭父进程不需要的fdclose(pipefd[1]);char buffer[1024] = {0};while (true){ssize_t s = read(pipefd[0], buffer, sizeof(buffer) - 1);if (s > 0){// buffer[s] = 0; // 填充结尾\0,但初始化时都初始化了0,此步省略cout << "child get a message[" << getpid() << "] Parent# " << buffer << endl;}else if(s == 0){cout << "writer quit, follow him :P" << endl;break;}}// close(pipefd[0]); // 这个位置可写可不写,反正下一步进程就退出exit(1);}// parent - write// 3.构建单向通信的信道// 3.1 关闭父进程不需要的fdclose(pipefd[0]);string msg = "我是父进程,我正在发消息";int count = 0;char send_buffer[1024];while(true){// 3.2 构建一个变化的字符串snprintf(send_buffer, sizeof(send_buffer), "%s[%d]:%d", msg.c_str(), getpid(), count++); // \0会自动追加到写入的内容之后// 3.3 写入write(pipefd[1], send_buffer, strlen(send_buffer));// 3.4 故意sleepsleep(1);if(count == 5){cout << "writer quie :P" << endl;break;}}close(pipefd[1]);pid_t ret = waitpid(id, nullptr, 0);return 0;
}

3.命名管道

0.为什么有命名管道?

  • 管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信
  • 如果想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道
  • 命名管道是一种特殊类型的文件

1.创建一个命名管道

  • 命名管道可以从命令行上创建命令:$ mkfifo filename
  • 命名管道也可以从程序里创建,函数:int mkfifo(const char *filename, mode_t mode);

2.命名管道原理

  • 如何让不同的进程看到同一份资源?
    • 在磁盘中创建一个文件,不同的进程同时打开它
    • 此文件可以被打开,但是不会将内存数据进行刷新到磁盘

3.匿名管道与命名管道的区别

  • 匿名管道由pipe函数创建并打开
  • 命名管道由mkfifo函数创建,打开用open
  • FIFO(命名管道)与pipe(匿名管道)之间唯一的区别在它们创建与打开的方式不同,一但这些工作完成之后,它们具有相同的语义

4.命名管道的打开规则

  • 如果当前打开操作是为而打开FIFO时:
    • O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO
    • O_NONBLOCK enable:立刻返回成功
  • 如果当前打开操作是为而打开FIFO时:
    • O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO
    • O_NONBLOCK enable:立刻返回失败,错误码为ENXIO

5.思考问题

  • 多个进程在通过管道通信时,删除管道文件则无法继续通信?
    • 错误
    • 管道的生命周期随进程,本质是内核中的缓冲区
    • 命名管道文件只是标识,用于让多个进程找到同一块缓冲区,删除后,之前已经打开管道的进程依然可以通信

6.使用 – 极其简化的代码,只供了解使用流程

  • comm.hpp
#define MODE 0666
#define SIZE 128
string ipcPath = "./fifo.ipc";
  • Server
void getMessage(int fd)
{char buffer[SIZE] = {0};while (true){ssize_t s = read(fd, buffer, sizeof(buffer) - 1);if(s > 0){cout << "[" << getpid() << "] "<< "client say " << buffer << endl;}else if (s == 0){// EOFcerr << "[" << getpid() << "] "<< "read end of file, client quit, server follow it :P" << endl;break;}else{// read errorperror("read");break;}}
}int main()
{// 1.创建管道文件if(mkfifo(ipcPath.c_str(), MODE) < 0){perror("mkfifo");exit(1);}// 2.正常的文件操作int fd = open(ipcPath.c_str(), O_RDONLY);int nums = 3;for (int i = 0; i < nums; i++){pid_t id = fork();if(id == 0){// 3.编写正常的通信代码getMessage(fd);exit(1);}}for (int i = 0; i < nums; i++){waitpid(-1, nullptr, 0);}// 4.关闭文件close(fd);unlink(ipcPath.c_str()); // 通信完毕,就删除文件return 0;
}
  • Client
int main()
{// 1.获取管道文件int fd = open(ipcPath.c_str(), O_WRONLY);// 2.ipc过程string buffer;while(true){cout << "Please Enter Message Line:> ";std::getline(std::cin, buffer);write(fd, buffer.c_str(), buffer.size());}close(fd);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/825226.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

目标检测——食品饮料数据集

一、重要性及意义 对食品和饮料进行目标检测的重要性和意义体现在多个方面&#xff1a; 商业应用与市场分析&#xff1a;目标检测技术在食品和饮料行业有着广泛的应用前景。通过对超市货架、餐馆菜单或广告海报中的食品和饮料进行自动识别和计数&#xff0c;商家可以获取关于产…

【微服务】spring状态机模式使用详解

一、前言 在很多系统中,通常会涉及到某个业务需要进行各种状态的切换操作,例如在审批流程场景下,某个审批的向下流转需要依赖于上一个状态的结束,再比如电商购物场景中,一个订单的生命周期往往伴随着不同的状态,比如待支付,支付完成,已发货等等,状态的存在,让一个业…

登录解析(后端)

调试登录接口 进入实现类可以有 验证码校验 登录前置校验 用户验证 验证码校验 通过uuid获取redis 中存储的验证码信息&#xff0c;获取后对用户填写的验证码数据进行校验比对 用户验证 1.进入控制器的 /login 方法 2.进入security账号鉴权功能&#xff0c;经过jar内的流…

HTML:Form表单控件主要标签及属性。name属性,value属性,id属性详解。表单内容的传递流程,get和post数据传递样式。表单数据传递实例

form表单 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </head> &…

c语言中什么是冒泡排序,冒泡排序的计算

在c语言中&#xff0c;冒泡排序的解释是&#xff0c;将被排序的记录数组arr[1..n]垂直排列&#xff0c;每个记录arr看作是重量为一个arr气泡。根据轻气泡不能在重气泡之下的原则&#xff0c;从下往上扫描数组arr&#xff0c;凡扫描到违反该原则的轻气泡&#xff0c;就使其向上飘…

算法练习第19天|222.完全二叉树的节点个数

222.完全二叉树的节点个数 222. 完全二叉树的节点个数 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/count-complete-tree-nodes/description/ 题目描述&#xff1a; 给你一棵 完全二叉树 的根节点 root &#xff0c;求出该树的节点个数。题目数据保…

振动信号幅值成分分析手段

提示&#xff1a;振动信号幅值成分分析手段 文章目录 一、特征值分析二、概率密度分析2.1、原理2.2、代码2.3、结果分析 三、总结&#xff08;自己的思想&#xff09; 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、特征值分析 均值和平均幅值可以…

【缓存常见问题】

在使用缓存时特别是在高并发场景下会遇到很多问题&#xff0c;常用的问题有缓存穿透、缓存击穿、缓存雪崩以及缓存一致性问题。 1、缓存穿透 首先&#xff0c;什么是缓存穿透呢&#xff1f; 缓存穿透是指请求一个不存在的数据&#xff0c;缓存层和数据库层都没有这个数据&…

虚拟天空解决方案,创造出令人惊叹的换天效果

在汽车视频领域&#xff0c;如何打破传统拍摄限制&#xff0c;呈现出更具创意和想象力的画面&#xff0c;成为众多企业和创作者追求的目标。美摄科技作为业界领先的视频技术提供商&#xff0c;凭借其强大的AI技术和三维渲染引擎&#xff0c;推出了全新的虚拟天空解决方案&#…

集成电路测试学习

集成电路&#xff08;Integrated Circuit&#xff0c;IC&#xff09;整个设计流程包括&#xff1a;电路设计、晶圆制造、晶圆测试、IC封装、封装后测试。 IC测试目的&#xff1a;一、确认芯片是否满足产品手册上定义的规范&#xff1b;二、通过测试测量&#xff0c;确认芯片可以…

李国武:QFD是如何将顾客需求转换为产品技术要求的?

如何将顾客的多样化需求精准地转化为产品的技术要求&#xff0c;成为企业赢得市场、提升竞争力的关键。质量功能展开&#xff08;Quality Function Deployment&#xff0c;简称QFD&#xff09;作为一种先进的质量管理工具&#xff0c;正是实现这一转换的有效桥梁。具体如天行健…

vim相关指令

vim的各种模式及其转换关系图 vim 默认处于命令模式&#xff01;&#xff01;&#xff01; 模式之间转换的指令 除【命令模式】之外&#xff0c;其它模式要切换到【命令模式】&#xff0c;只需要无脑 ESC 即可&#xff01;&#xff01;&#xff01; [ 命令模式 ] 切换至 [ 插…

unity动画的关键帧添加event-同步语音

在iclone中做的语音嘴型动画&#xff0c;因是用下图自带的方式语音生成的动画&#xff0c;而不是用plugin(面捕live会连同语音一起导出)&#xff0c;所以导出来到Unity中&#xff0c;之后口型、动作、表情等没有声音。 我需要把原有的语音也重新在unity中加载上&#xff0c;原来…

解决WPS右键菜单冗余选项,去除WPS右键菜单选项

问题描述 安装WPS后&#xff0c;右键菜单会多出许多无用的选项&#xff0c;如何去除&#xff1f; 解决方法 按下WindowsS打开搜索栏&#xff0c;搜索配置工具打开 勾选所有的关闭和隐藏选项

汽车视频智能剪辑解决方案,满足用户对高品质汽车视频的追求

随着汽车智能化和互联网技术的快速发展&#xff0c;车载视频已经成为现代驾驶生活不可或缺的一部分。然而面对海量的行车视频&#xff0c;如何高效地剪辑、整理并分享这些精彩瞬间&#xff0c;一直是车主和汽车内容创作者们所面临的难题。美摄科技&#xff0c;作为领先的视频智…

Postgres数据库中的死锁是如何产生的,如何避免和解决?

文章目录 死锁的产生原因如何避免死锁如何解决死锁示例代码查询死锁信息终止事务 在Postgres数据库中&#xff0c;死锁是一种特殊的情况&#xff0c;其中两个或多个事务相互等待对方释放资源&#xff0c;从而导致它们都无法继续执行。这种情况通常发生在多个事务尝试以不同的顺…

SQL255 给出employees表中排名为奇数行的first_name

题目来源&#xff1a; 给出employees表中排名为奇数行的first_name_牛客题霸_牛客网 描述 对于employees表中&#xff0c;输出first_name排名(按first_name升序排序)为奇数的first_name CREATE TABLE employees ( emp_no int(11) NOT NULL, birth_date date NOT NULL, firs…

高德地图API-鼠标点击地图获取经纬度坐标(关键操作)

效果图&#xff1a; 有了经纬度坐标&#xff0c;就可以得到城市的&#xff1a;adcode区域编码 html版本 <!doctype html> <html> <head><meta charset"utf-8"><meta http-equiv"X-UA-Compatible" content"IEedge"&g…

Unity类银河恶魔城学习记录13-1 p142 Save system源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili FileDataHandler.cs using System; using System.IO; using UnityEngine; p…

数据结构学习记录

数据结构 数组 & 链表 相连性 | 指向性 数组可以迅速定位到数组中某一个节点的位置 链表则需要通过前一个元素指向下一个元素&#xff0c;需要前后依赖顺序查找&#xff0c;效率较低 实现链表 // head > node1 > node2 > ... > nullclass Node {constructo…