【linux】进程间通信(匿名管道)

对于本篇文章我们采取三段论:是什么 为什么 怎么办。

目录

  • 进程间为什么要通信?
  • 进程间如何通信?
  • 进程间怎么通信?
    • 匿名管道:
      • 匿名管道原理:
      • 代码示例:
      • 匿名管道的情况与特征:

进程间为什么要通信?

进程间也是需要某种协同的。
协同应该怎么理解呢?
在这里插入图片描述
那么协同的前提必然是进行通信
但是通信的信息也是有类别的,比如说单纯的数据信息,或者控制信息…

了解了这个话题我们还要在阐述一个事实,进程间具有独立性:比如关闭你的QQ但是不影响微信。
进程 = 内核数据结构 + 数据与代码
那么这两份东西每个进程都是有独一份的,数据与代码会写时拷贝,所以不影响我们这个结论。

进程间如何通信?

这里我们要明确两个共识:
a. 进程间通信是有成本的(这个会在后边的代码中有验证)
b. 进程间通信的前提:让两个进程看到同一块内存资源

我们画图进行理解一下:
在这里插入图片描述

进程间怎么通信?

开始这个话题之前我们需要先知道一个东西:
互联网有大量标准的存在,否则为什么不同品牌的手机,不同大陆的手机厂商,用着不一样的硬件设备最后却能进行通信?
就是因为标准的存在!

所以我们进程间通信也有标准,这里我们只谈System V
这个标准提供了一些通信方式:

  1. 消息队列
  2. 共享内存
  3. 信号量

但是,人们刚接触通信时肯定是先想到尽量复用源代码进行通信的,故我们暂且不谈以上的方式(未来会谈)。
所以我们利用源代码设计出了两种方式

  1. 匿名管道
  2. 有名管道

这里我们先说匿名管道,因为他简单。

匿名管道:

匿名管道原理:

下图是一幅进程,文件与磁盘的简略图:
在这里插入图片描述
当对此文件以另一种方式打开时,变化如下
在这里插入图片描述
为什么答案是否定的呢?
在这里插入图片描述

那么当前进程fork()(创建子进程)会发生什么变化?
在这里插入图片描述
所以,现在我们就可以以普通文件为切入点理解匿名管道了

首先父进程打开同一个文件以“w”“r”方式,然后在进行创建子进程,
子进程会继承父进程的文件系统那一套数据结构,
这样他们就有了公共的一块内存,也就是那段内核缓冲区,
我们此时就可以一个进程向其中写入,另一个读取
在这里插入图片描述

但是我们匿名管道并不是普通文件,

  • 第一:我们的匿名管道不需要与磁盘进行交互了,因此,设计者要重新设计出一个新的通信接口
  • 第二:我们的管道只允许单向通信,因为他简单!所以我们fork之后要关闭一个进程的w和另一个进程的r

因此我们现在要理解一种现象以及两个问题:
现象:为什么我们的父子进程会向同一块显示屏打印数据

问题1:既然未来要关闭不需要的fd,那我们可不可以直接不打开呢?
问题2:可以不关闭吗?

对于这种现象是因为我们的bash父进程就已经打开了fd为0 1 2的文件描述符,所以bash的子进程们都继承了,所以他们会向同一块fd为1指向的内存进行疯狂输出并刷新到显示屏外设

对于问题1:不可以,因为这样子进程就不会继承了。
对于问题2:可以,单位了防止我们有意外操作建议关闭!

代码示例:

话说了这么多我们总得有理论实践,我们会使用pipe接口+fork来创建管道。

下段这80行的代码可以帮助我们理解匿名管道的情况与特征:
代码中会有注释:

#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>const int SIZE = 1024;std::string GetOtherMessage()
{static int cnt = 1;int id = getpid();std::string MessageCnt = std::to_string(cnt++);std::string ChildId = std::to_string(id);return "MessageCnt: " + MessageCnt + " child id: " + ChildId +  + " ";
}子进程进行写入,但是我另外写了一段程序进行获取一段动态的信息。也就是如上的函数
void SubProcessWrite(int wfd)
{std::string message = "I am child,";while (true){std::string info = message + GetOtherMessage();write(wfd, info.c_str(), info.size());sleep(1);}
}父进程进行读
void FatherProcessRead(int rfd)
{char buffer[SIZE] = {0};while (true){ssize_t n = read(rfd, buffer, sizeof(buffer) - 1);if (n > 0){buffer[n] = 0;std::cout << "father get message:" << buffer << std::endl;}}
}int main()
{int pipefd[2];int ret = pipe(pipefd);if (ret == -1){std::cerr << "errno: " << errno << " errstring: " << std::strerror(errno) << std::endl;return 1;}pid_t id = fork();if (id == 0){std::cout << "我是子进程,已经关闭了0了" << std::endl;// 子进程,进行写,关闭rclose(pipefd[0]);SubProcessWrite(pipefd[1]);close(pipefd[1]);exit(0);}std::cout << "我是父进程,已经关闭了1了" << std::endl;// 父进程,进行读,关闭wclose(pipefd[1]);FatherProcessRead(pipefd[0]);close(pipefd[0]);// 父进程进行等待int rid = waitpid(id, nullptr, 0);if (rid > 0){std::cout << "wait sucess" << std::endl;}return 0;
}

匿名管道的情况与特征:

对于下边情况的验证我们都可以通过对上边的程序进行修改得到结果。

四种情况:
在这里插入图片描述

在这里插入图片描述
对于2,我们可以将上面的程序进行一下修改在这里插入图片描述
同时让父进程sleep更长的时间,得到管道的大小为64kb(ubuntu22.04)

在这里插入图片描述
在这里插入图片描述
至于为什么不会阻塞是因为管道已经失效了。
在这里插入图片描述
首先我们要对这种情况进行一个探究,读端已经被关闭,说明写再多也没有用,OS不会允许这种浪费时空的东西存在,会直接杀掉写进程。
用什么杀死呢?
OS发送13号信号进行终止。

此时的这个管道也叫做broken pipe。


五种特征:

  1. 匿名管道:只能用于有血缘关系的进程之间,常用于父子进程。

  2. 管道之间自带进程的同步机制。
    (同步理解为多执行流代码的时候,具有顺序性)
    在这里插入图片描述

  3. 管道文件的生命周期是随进程的

  4. 管道文件再通信的时候是面向字节流的(可以认为write的次数与read的次数不是一一匹配的,就像你用的水是从自然界收集来的,自然界用了10小时收集的水,你1分钟用完了)

  5. 管道的通信模式是一种特殊的半双工模式
    我们先来说一下全双工模式->类似于我们吵架时,我们可以同时说话
    半双工就是一个人说,一个人不说,或者相反过来
    而我们这个特殊的半双工就特殊在只能单向,只能一段说话,另一端不说话。

最后我们在输出最后一个结论:
我们在上文提到过:我们具有同步机制,但其实这不是一定的,当我们每次写入数据小于PIPE_BUF时才会具有这种机制,也叫作原子态(atomic)
在这里插入图片描述
匿名管道就结束啦!

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

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

相关文章

win下vscode的vim切换模式的中英文切换

问题描述 在vscode中安装vim插件后&#xff0c;如果insert模式下完成输入后&#xff0c;在中文输入方式下按esc会发生无效输入&#xff0c;需要手动切换到英文。 解决方法 下载完成vscode并在其中配置vim插件下载github—im-select.exe插件&#xff08;注意很多博文中的gitcod…

【MySQL篇】使用mysqldump全量+mysqlbinlog增量完成实例的全库恢复(第四篇,总共四篇)

☘️博主介绍☘️&#xff1a; ✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ ✌✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux&#xff0c;也在扩展大数据方向的知识面✌✌️ ❣️❣️❣️大佬们都喜欢静静的看文章&am…

每天五分钟深度学习框架pytorch:如何创建多维Tensor张量元素?

本文重点 上节课程我们学习了如何创建Tensor标量,我们使用torch.tensor。本节课程我们学习如何创建Tensor向量,我们即可以使用torch.Tensor又可以使用torch.tensor,下面我们看一下二者的共同点和不同点。 Tensor张量 tensor张量是一个多维数组,零维就是一个点(就是上一…

【数据结构】链表专题3

前言 本篇博客我们继续来讨论链表专题&#xff0c;今天的链表算法题是经典中的经典 &#x1f493; 个人主页&#xff1a;小张同学zkf ⏩ 文章专栏&#xff1a;数据结构 若有问题 评论区见&#x1f4dd; &#x1f389;欢迎大家点赞&#x1f44d;收藏⭐文章 目录 1.判断链表是否…

ROS1快速入门学习笔记 - 014launch启动文件的使用方法

一、定义 Launch文件&#xff1a;通过XML文件实现多节点的配置和启动&#xff08;可自动启动ROSMaster&#xff09; 二、常用语法 1. 根标签 <launch> - launch文件中的根元素采用<launch>标签定义 <launch>表示开始&#xff1b;<launch>表示结束&…

AD | Altium Designer(原理图设计、电路仿真、PCB绘图)汉化版

Altium Designer(原理图设计、电路仿真、PCB绘图) 通知公告 Altium Designer(AD)是一种功能强大的电子设计自动化(EDA)软件。它主要用于设计和开发电子产品,如电路板(PCB)、集成电路(IC)和嵌入式系统。AD提供了完整的设计工具套件,包括原理图设计、PCB布局、仿真、设…

40.WEB渗透测试-信息收集-域名、指纹收集(2)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;39.WEB渗透测试-信息收集-域名、指纹收集&#xff08;1&#xff09; oneforall的安装前置…

基于粒子滤波器的电池剩余使用寿命计算matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 粒子滤波器基础 4.2 电池剩余使用寿命建模与预测 4.3 粒子滤波器在电池寿命预测中的应用 5.完整工程文件 1.课题概述 基于粒子滤波器的电池剩余使用寿命计算。根据已知的数据&#xff0c;预测未来…

OPPO A72/A55/K7X/A53真我Q3S等手机ROOT刷机后广电卡没信号不读卡解决办法

目前运营商除了移动联通电信以外&#xff0c;还存在1个中国广电&#xff0c;广电属于第四大运营商&#xff0c;由于广电起步较晚&#xff0c;对于手机频段要求也自然不一样&#xff0c;导致目前市面上部分手机出厂没有信号或者不读卡等问题&#xff0c;特别在手机被用户自行刷机…

二叉树的遍历算法

目录 1.二叉树结构 2.广度优先搜索二叉树&#xff08;迭代算法&#xff09; 3.深度优先搜索二叉树&#xff08;递归算法&#xff09; 1.二叉树结构 一个父结点&#xff0c;至多可以连接左右两个子节点 Java构造树结构——其实是 自定义树结点类型 public class TreeNode {in…

信号,信号列表,信号产生方式,信号处理方式

什么是信号 信号在我们的生活中非常常见&#xff1b;如红绿灯&#xff0c;下课铃&#xff0c;游戏团战信号&#xff0c;这些都是信号&#xff1b;信号用来提示接收信号者行动&#xff0c;但接收信号的人接收到信号会进行一系列的行为&#xff0c;完成某个动作&#xff1b;这就…

cmake的使用方法: 多个源文件的编译

一. 简介 前面一篇文章学习了针对只有一个 .c源文件&#xff0c;如何编写 CMakeLists.txt内容&#xff0c;从而使用 cmake工具如何编译工程。文章如下&#xff1a; cmake的使用方法: 单个源文件的编译-CSDN博客 本文学习针对 多个 .c源文件&#xff0c; CMakeLists.txt文件如…

融创共赢,算网领航 | 移动云智能芯片开放实验室正式发布

4月29日上午&#xff0c;中国移动算力网络大会“融创共赢&#xff0c;算网领航-算网原生技术”分论坛在苏州金鸡湖国际会议中心顺利召开&#xff0c;中国移动云能力中心副总经理吴世俊出席论坛并发表致辞。大会举行了智能芯片开放实验室发布仪式&#xff0c;同时发布移动云最新…

CogAgent:开创性的VLM在GUI理解和自动化任务中的突破

尽管LLMs如ChatGPT在撰写电子邮件等任务上能够提供帮助&#xff0c;它们在理解和与GUIs交互方面存在挑战&#xff0c;这限制了它们在提高自动化水平方面的潜力。数字世界中的自主代理是许多现代人梦寐以求的理想助手。这些代理能够根据用户输入的任务描述自动完成如在线预订票务…

【模板】前缀和

原题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 前缀和模板题。 前缀和中数组下标为1~n。 前缀和&#xff1a;pre[i]pre[i-1]a[i]; 某段区间 [l,r]的和&#xff1a;pre[r]-pre[l-1] 3.…

android天气实战

页面绘制 问题1、下拉框需要背景为透明 我懒得写全部省份就写了5个所以不需要往下 图标准备 iconfont-阿里巴巴矢量图标库几坤年没来这了好怀念啊&#xff0c;图标库选择下雨的图标等 准备网络请求 0、API接口准备 api免费七日天气接口API 未来一周天气预报api (tianqiap…

前端业务开发中使用原生js和elementui两种方式实现头像裁切上传的功能

日常业务开发中&#xff0c;无论是后台管理系统还是前台界面&#xff0c;都会遇到图片裁剪的业务需求&#xff0c;选择合适的尺寸或者图片的关键部分&#xff0c;满足我们的功能需求&#xff01;&#xff01; 效果预览 效果一&#xff1a; 效果二: 实现过程 1.原生js实现方…

VS(Visual Studio)中查找项目里的中文字符

目录 正则表达式查找中文字符 正则表达式查找中文字符 在Visual Studio (VS) 中查找所有的中文字符&#xff0c;你可以使用其强大的查找和替换功能。不过&#xff0c;由于中文字符的范围非常广泛&#xff08;包括简体中文、繁体中文、日本汉字、韩国汉字等&#xff09;&#xf…

GPT3 终极指南(一)

原文&#xff1a;zh.annas-archive.org/md5/6de8906c86a2711a5a84c839bec7e073 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 前言 GPT-3&#xff0c;或者说是 Generative Pre-trained Transformer 3&#xff0c;是由 OpenAI 开发的基于 Transformer 的大型语言模型…

平安城市 校园 景区 停车场网络语音对讲立柱SV-11TS

平安城市 校园 景区 停车场网络语音对讲立柱SV-11TS 长方形立柱式设计&#xff0c;外观简约&#xff0c;线条优美&#xff0c;工艺考究&#xff0c;坚固耐用可一键实现在紧急情况下求助报警、事件咨询&#xff0c;与SIP网络对讲主机进行全双工对讲。内置警示灯&#xff0c;呼叫…