当前位置: 首页 > news >正文

进程间通信之管道

文章目录

  • 一、管道
    • 1. 匿名管道
    • 2. 命名管道

进程具有独立性,因此进程间通信的前提是两个进程能看到同一份资源

一、管道

对于进程打开的内存文件,操作系统是以引用计数的方式创建的 file 结构体,如果让两个进程与同一个 file 结构体关联,便可以让两个进程看到同一份资源

由于 file 结构体的缓冲区只有一个,因此只能让一个进程以写的方式,另一个进程以读的方式打开同一个文件,这样便实现了单向的进程间通信
在这里插入图片描述
操作系统提供了仅在内存中创建 file 结构体(不在磁盘上创建对应的文件),这种特殊的文件称为管道文件,其中没有名字的称为 匿名管道,有名字的称为 命名管道

1. 匿名管道

进程创建匿名管道成功后,会以读和写两种方式打开管道文件,因此匿名管道通常用于父子进程的进程间通信

系统调用 pipe,头文件 unistd.h

  • int pipe(int pipefd[2]),创建匿名管道

返回值:匿名管道创建成功返回 0,出错返回 -1,并且 errno 被设置为相应的出错信息

参数:pipefd 为输出型参数,pipefd[0] 存储读端文件描述符,pipefd[1] 存储写端文件描述符

父子进程通信的步骤:

  • 父进程创建管道
    父进程以读和写两种方式打开管道文件
  • 创建子进程
    子进程会拷贝父进程的文件描述符表,因此子进程也会以读和写两种方式打开同一个管道文件
  • 父进程和子进程分别关闭自己不需要的读端或写端
    一个进程向管道中写入,另一个进程从管道中读取

子进程向匿名管道写入,父进程从匿名管道读取

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cerrno>
#include <cassert>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>using namespace std;int main()
{// 创建匿名管道// pipefd[0] 表示读// pipefd[1] 表示写int pipefd[2] = { 0 };if (pipe(pipefd) < 0){// 创建匿名管道失败cout << "匿名管道创建失败: " << errno << " " << strerror(errno) << endl;exit(1);}// 创建子进程pid_t id = fork();assert(id != -1);if (id == 0){// 子进程向匿名管道写入,需要关闭读close(pipefd[0]);// 开始通信int cnt = 0;char buffer[64];while (true){snprintf(buffer, sizeof(buffer), "我是子进程,这是我给你发的第 %d 个信息", ++cnt);// 向匿名管道中写入write(pipefd[1], buffer, strlen(buffer));cout << cnt << endl;// sleep(1); // 让写端慢一点// if (cnt == 3) break; // 模拟写端关闭}close(pipefd[1]);exit(0);}// 父进程从匿名管道读取,需要关闭写close(pipefd[1]);// 开始通信char buffer[64];while (true){// 从匿名管道中读取// sleep(3); // 让读端慢一点// sleep(3); break; // 模拟读端关闭int n = read(pipefd[0], buffer, sizeof(buffer) - 1);if (n > 0){        buffer[n] = '\0';cout << buffer << endl;}else if (n == 0){cout << "写端已经关闭,我读到文件结尾了" << endl;break;}else{cout << "读取错误" << endl;break;}}close(pipefd[0]);// 读端关闭,写端会收到 13 号信号 SIGPIPEint status;waitpid(id, &status, 0);cout << "子进程退出信号: " << (status & 0x7F) << endl;return 0;
}
  • 放开子进程代码中的 sleep(1),让写端慢一点,匿名管道中没有数据时,读端会等待写端写入
    在这里插入图片描述
  • 放开父进程中的 sleep(3),让读端慢一点,匿名管道中写满数据时,写端会等待读端读取
    在这里插入图片描述
  • 放开子进程中模拟写端关闭的代码,并且让写端慢一点,写端关闭后,读端读取完匿名管道中的数据后,读端会读取到文件结尾
    在这里插入图片描述
  • 放开子进程中模拟读端关闭的代码,并且让写端慢一点,读端关闭时,此时匿名管道无意义,操作系统会向写端发送 SIGPIPE 13 号信号
    在这里插入图片描述

命令行中的 | 即为匿名管道,| 会将前一个进程的标准输出重定向到匿名管道,后一个进程的标准输入重定向到匿名管道

在这里插入图片描述

通过匿名管道创建进程池:

// processpool.hpp
#include <iostream>
#include <vector>
#include <functional>
#include <cstring>
#include <cerrno>
#include <cassert>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>namespace starrycat
{class EndPoint{public:EndPoint(){}EndPoint(pid_t cid, int wfd) : _cid(cid), _wfd(wfd){}~EndPoint(){}public:pid_t _cid;int _wfd;};const int NUM = 5;class ProcessPool{using fun_t = std::function<void(int)>;public:ProcessPool(fun_t Command, int num = NUM){std::vector<int> tmpfd; // 保存子进程不需要的父进程的文件描述符for (int i = 0; i < num; ++i){// 创建管道int pipefd[2] = {0};if (pipe(pipefd) < 0){std::cout << "创建管道失败: " << errno << " " << strerror(errno) << std::endl;exit(1);}// 创建子进程int id = fork();assert(id != -1);if (id == 0){// 子进程从管道中读取,需要关闭写close(pipefd[1]);for (auto e : tmpfd) close(e); // 关闭不需要的文件描述符// 开始通信while (true){// 读取四字节整数的命令int cmd = 0;int n = read(pipefd[0], &cmd, sizeof(int));if (n == sizeof(int)){// 测试std::cout << getpid() << " ";// 执行命令Command(cmd);}else if (n == 0){// 测试std::cout << getpid() << " 读取到文件结尾了" << std::endl;break;}else{std::cout << "读取异常" << std::endl;break;}}close(pipefd[0]);exit(0);}// 父进程向管道中写入,需要关闭读close(pipefd[0]);_endPoints.push_back(EndPoint(id, pipefd[1]));tmpfd.push_back(pipefd[1]);}}ProcessPool(const ProcessPool &p) = delete;ProcessPool &operator=(const ProcessPool &p) = delete;~ProcessPool(){for (auto& e : _endPoints) {close(e._wfd);waitpid(e._cid, nullptr, 0);// 测试std::cout << "等待子进程:" << e._cid  << "成功" << std::endl;sleep(1);}}// 规定命令为四字节整数void push(int command){// 以轮训的方式调用子进程static int index = 0;write(_endPoints[index]._wfd, &command, sizeof(int));index++;index %= _endPoints.size();}private:std::vector<EndPoint> _endPoints;};
}// myctrlprocess.cc
#include "processpool.hpp"
#include <iostream>
#include <string>using namespace std;// 子进程个数
const int num = 5;void PrintLog()
{cout << "打印日志任务,正在被执行..." << endl;
}void InsertMySQL()
{cout << "执行数据库任务,正在被执行..." << endl;
}void NetQuest()
{cout << "执行网络请求任务,正在被执行..." << endl;
}void CommandError()
{cout << "任务不存在" << endl;
}void Command(int cmd)
{switch (cmd){case 0:PrintLog();break;case 1:InsertMySQL();break;case 2:NetQuest();break;default:CommandError();break;}
}int main()
{starrycat::ProcessPool ppool(Command);int command = 0;while (true){cout << "请输入命令: ";cin >> command;// 测试if (command == -1) break;ppool.push(command);sleep(1);}return 0;
}

2. 命名管道

命名管道支持两个毫不相关的进程通信,其使用和文件一样

系统调用 mkfifo,头文件 sys/types.h、sys/stat.h

  • int mkfifo(const char *pathname, mode_t mode),创建命名管道

返回值:命名管道创建成功返回 0,出错返回 -1,并且 errno 被设置为相应的出错信息

参数:

  • pathname 表示创建命名管道的路径名(如果只有文件名,则表示在进程所在的路径下创建)
  • mode 表示创建命名管道的文件权限,受 umask 影响

客户端向命名管道写入,服务端从命名管道读取

// namepipe.h
#pragma once// 命名管道文件名
const char* const fifoname = "fifo";// client.cc
#include "namepipe.h"
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cerrno>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>using namespace std;int main()
{// 以写方式打开命名管道int wfd = open(fifoname, O_WRONLY);if (wfd < 0){cout << "打开文件失败" << errno << " " << strerror(errno) << endl;exit(1);}// 开始通信char buffer[1024];while (true){cout << "请输入: ";char* str = fgets(buffer, sizeof(buffer), stdin);if (str == NULL){cout << "客户端退出" << endl;break;}buffer[strlen(buffer) - 1] = '\0'; // 去掉输入的回车符// 输入 quit 表示客户端退出if(strcmp(buffer, "quit") == 0) {cout << "客户端退出" << endl;break;}// 向命名管道写入write(wfd,  buffer, strlen(buffer));}close(wfd);return 0;
}// server.cc
#include "namepipe.h"
#include <iostream>
#include <cerrno>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>using namespace std;int main()
{// 创建命名管道umask(0);  // 设置进程的权限掩码if (mkfifo(fifoname, 0666) < 0){cout << "创建管道失败: " << errno << " " << strerror(errno) << endl;exit(1);}// 以读方式打开命名管道int rfd = open(fifoname, O_RDONLY);if (rfd < 0){cout << "打开文件失败" << errno << " " << strerror(errno) << endl;}// 开始通信char buffer[1024];while (true){// 从命名管道读取int n = read(rfd, buffer, sizeof(buffer) - 1);if (n > 0){buffer[n] = '\0';cout << "客户端: " << buffer << endl;}else if (n == 0){cout << "客户端退出了,服务端也退出" << endl;break;}else{cout << "读取异常" << endl;break;}}close(rfd); unlink(fifoname); // 删除命名管道return 0;
}

先启动 myserver,在启动 myclient

在这里插入图片描述

命名管道和匿名管道的通信特性是一样的

mkfifo 文件名
功能:创建命名管道

在这里插入图片描述

相关文章:

进程间通信之管道

文章目录 一、管道1. 匿名管道2. 命名管道 进程具有独立性&#xff0c;因此进程间通信的前提是两个进程能看到同一份资源 一、管道 对于进程打开的内存文件&#xff0c;操作系统是以引用计数的方式创建的 file 结构体&#xff0c;如果让两个进程与同一个 file 结构体关联&…...

f12 CSS网页调试_css样式被划了黑线怎么办

我的问题是这样的 class加上去了,但是样式不生效,此时可能是样式被其他样式覆盖了, 解决方案就是 给颜色后边添加一个!important...

vue-制作自动滚动效果

第一步&#xff1a;下载 可以查看官方地址chenxuan0000 npm i vue-seamless-scroll -save 第二步&#xff1a;引用 import vueSeamlessScroll from "vue-seamless-scroll";//注册components: {vueSeamlessScroll,}, 第三步&#xff1a;使用 <vue-seamless…...

[国产MCU]-BL602-开发实例-DMA数据传输

DMA数据传输 文章目录 DMA数据传输1、DMA介绍2、DMA驱动API介绍3、DMA使用示例DMA(Direct Memory Access)是一种内存存取技术,可以独立地直接读写系统内存,而不需处理器介入处理。 在同等程度的处理器负担下,DMA是一种快速的数据传送方式。 BL602的DMA控制器有4组独立专用通…...

Redis压缩列表

区分一下 3.2之前 Redis中的List有两种编码格式 一个是LINKEDLIST 一个是ZIPLIST 这个ZIPLIST就是压缩列表 3.2之后来了一个QUICKLIST QUICKLIST是ZIPLIST和LINKEDLIST的结合体 也就是说Redis中没有ZIPLIST和LINKEDLIST了 然后在Redis5.0引入了LISTPACK用来替换QUiCKLIST中的…...

【SA8295P 源码分析】62 - Android GVM Kernel 内核 make bootimage 过程分析

【SA8295P 源码分析】62 - Android GVM Kernel 内核 make bootimage 过程分析 一、make bootimage 命令执行过程分析1.1 source buid/envsetup.sh 分析1.2 lunch msmnile_gvmq-userdebug 分析1.3 make bootimage:step 1 之 加载配置文件过程分析1.4 make bootimage:step 2 之…...

机器学习——SMO算法推导与实践

一、 硬间隔-SMO算法推导 明天再说&#xff0c;啊。。。。感觉天空明朗了很多&#xff0c;即使现在已经很晚了 还是要打开柯南&#xff0c;看看电视&#xff0c;等待天气预报所说的台风天吧&#xff01; 一时之间&#xff0c;忽然失去了用markdown语法写下推导过程的勇气。。。…...

mac的终端通过code .指令快速启动vscode

通过在vscode中安装"code"命令工具 打开vsocode&#xff0c;使用快捷键⇧⌘P&#xff0c;然后输入shell&#xff0c;会弹出来“Shell命令&#xff1a;在PATH中安装‘code’命令”浮窗&#xff0c;选择安装就可以了&#xff0c;然后就可以在终端通过code .来快速启动…...

前端系统使用iframe下载文件

需求描述 前端调用后端的接口&#xff0c;获取到文件的路径&#xff0c;并下载。 碰到的问题 页面组件存在与云端的组件库&#xff0c;使用window.open()无法满足需求&#xff08;在当前页面下载&#xff09;&#xff0c;因为路径是跨域的&#xff0c;所以决定使用iframe的方…...

RabbitMQ - 简单案例

目录 0.引用 1.Hello world 2.轮训分发消息 2.1 抽取工具类 2.2 启动两个工作线程接受消息 2.4 结果展示 3.消息应答 3.1 自动应答 3.2 手动消息应答的方法 3.3 消息自动重新入队 3.4 消息手动应答代码 4.RabbitMQ 持久化 4.1 队列如何实现持久化 4.2 消息实现持久化 5.不…...

《吐血整理》高级系列教程-吃透Fiddler抓包教程(30)-Fiddler如何抓Android7.0以上的Https包-番外篇

1.简介 通过宏哥前边几篇文章的讲解和介绍想必大家都知道android7.0以上&#xff0c;有android的机制不在信任用户证书&#xff0c;导致https协议无法抓包。除非把证书装在系统信任的证书里&#xff0c;此时手机需要root权限。但是大家都知道root手机是非常繁琐的且不安全&…...

服务器被攻击了怎么办?

服务器被攻击是无法避免的&#xff0c;但是我们能通过做好防护措施&#xff0c;提高服务器的安全性&#xff0c;降低被攻击的几率。那么当服务器已经被 攻击了&#xff0c;怎样才能降低损失呢&#xff1f;该怎样补救&#xff1f; 断开网络 全部的攻击都来自于网络&#xff0c;因…...

P1156 垃圾陷阱(背包变形)

垃圾陷阱 题目描述 卡门――农夫约翰极其珍视的一条 Holsteins 奶牛――已经落了到 “垃圾井” 中。“垃圾井” 是农夫们扔垃圾的地方&#xff0c;它的深度为 D D D&#xff08; 2 ≤ D ≤ 100 2 \le D \le 100 2≤D≤100&#xff09;英尺。 卡门想把垃圾堆起来&#xff0c…...

[Docker实现测试部署CI/CD----构建成功后钉钉告警(7)]

目录 15、钉钉告警创建项目群&#xff0c;然后添加机器人添加机器人Jenkins 系统配置项目配置修改Jenkinsfile文件&#xff0c;添加钉钉提示信息测试 不修改Jenkinsfile文件&#xff0c;添加钉钉提示信息测试 15、钉钉告警 创建项目群&#xff0c;然后添加机器人 首先需要在钉…...

UE5 半透明覆层材质

文章目录 前言介绍示例1示例2示例3 前言 本文采用虚幻5.2.1版本演示&#xff0c;介绍半透明覆层材质&#xff08;覆层材质&#xff09;。 介绍 半透明覆层材质是 UE5.1 版本 更新的功能&#xff0c;使用半透明覆层材质&#xff0c;可以轻松的给物体表面附着一层材质。 在UE5…...

在Raspberry Pi 4上安装Ubuntu 20.04 + ROS noetic(不带显示器)

在Raspberry Pi 4上安装Ubuntu 20.04 ROS noetic&#xff08;不带显示器&#xff09; 1. 所需设备 所需设备&#xff1a; 树莓派 4 B 型 wifi microSD 卡&#xff1a;最小 32GB MicroSD 转 SD 适配器 &#xff08;可选&#xff09;显示器&#xff0c;鼠标等 2. 树莓派…...

CommStudio for .NET Crack

CommStudio for .NET Crack CommStudio for.NET使您的应用程序可以轻松地使用串行端口和调制解调器进行通信。CommStudio for.NET是一套全面的组件和可视化调试工具&#xff0c;可将远程系统和设备与visual Studio 2005和visual Studio 2008集成。开发与遗留系统和外部设备集成…...

蓝桥杯上岸考点清单 (冲刺版)!!!

大家好 我是寸铁&#x1f4aa; 真题千千万万遍&#xff0c;蓝桥省一自然现&#xff01; ✌️ 日更3000里&#xff0c;蓝桥眷顾你 &#x1f31f; 暴力出奇迹&#xff0c;打表过样例 &#x1f44a; 冲刺蓝桥杯省一模板大全来啦 &#x1f525; 蓝桥杯4月8号就要开始了 &#…...

AI一键生成短视频

AI一键生成推文短视频 阅读时长&#xff1a;10分钟 本文内容&#xff1a; 结合开源AI&#xff0c;一键生成短视频发布到常见的某音&#xff0c;某手平台&#xff0c;狠狠赚一笔 前置知识&#xff1a; 1.基本的 python 编程知识 2.chatGPT 使用过 3.stable diffution 使用过 成果…...

基于MATLAB长时间序列遥感数据分析(以MODIS数据处理为例)

MATLAB MATLAB是美国MathWorks公司出品的商业数学软件&#xff0c;用于数据分析、无线通信、深度学习、图像处理与计算机视觉、信号处理、量化金融与风险管理、机器人&#xff0c;控制系统等领域。 [1] MATLAB是matrix&laboratory两个词的组合&#xff0c;意为矩阵工厂&a…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

【JVM】Java虚拟机(二)——垃圾回收

目录 一、如何判断对象可以回收 &#xff08;一&#xff09;引用计数法 &#xff08;二&#xff09;可达性分析算法 二、垃圾回收算法 &#xff08;一&#xff09;标记清除 &#xff08;二&#xff09;标记整理 &#xff08;三&#xff09;复制 &#xff08;四&#xff…...

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务&#xff0c;但是又不想花钱&#xff0c;所以就想着自己搭建一个&#xff0c;刚好我们用的一个开源框架已经集成了MinIO&#xff0c;所以就选了这个 我这边对文件服务性能要求不是太高&#xff0c;单机版就可以 安装非常简单&#xff0c;几个命令就…...

HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散

前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说&#xff0c;在叠衣服的过程中&#xff0c;我会带着团队对比各种模型、方法、策略&#xff0c;毕竟针对各个场景始终寻找更优的解决方案&#xff0c;是我个人和我司「七月在线」的职责之一 且个人认为&#xff0c…...

论文阅读:Matting by Generation

今天介绍一篇关于 matting 抠图的文章&#xff0c;抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法&#xff0c;已经有很多的工作和这个任务相关。这两年 diffusion 模型很火&#xff0c;大家又开始用 diffusion 模型做各种 CV 任务了&am…...