进程通信方式——管道

什么是管道

管道是进程间通信的一种方式,它的本质其实是内核中的一块内存(或者说是内核缓冲区),这块区域的数据存储在一个环形队列,不过由于管道使用的是内核里面 的内存,所以我们无法对管道里面的数据进行直接操作,只能在管道的两端读/写数据。

管道的特点

  • 管道数据是基于队列来维护的

  • 管道对应的内核缓冲区大小的固定,默认4K

  • 管道分为两部分:读端和写端(队列的两端),数据从写端进入管道,从端流出管道

  • 管道的数据只能读一次,可以理解数据是在管道里面流动,由一端流向另一端.

  • 对管道的操作(读,写)默认是阻塞的

    • 读管道:管道中没有数据,读操作被阻塞,当管道中有数据之后阻塞才能解除。
    • 写管道:管道被写满了,写数据的操作被阻塞,当管道变为不满的状态,写阻塞解除。
    • Linux的文件IO函数:
    ssize_t read(int fd,void *buf,size_t count);
    ssize_t write(int fd,const void *buf,size_t count);
    

匿名管道

匿名管道的创建

匿名管道是管道的一种,匿名主要是指管道没有名字,但是本质是不变,它有管道的所有特性,匿名管道只能实现有血缘关系的进程间通信(父子进程,兄弟进程,爷孙进程,叔侄进程)

#include <unistd.h>
int pipe(int pipefd[2]);
  • 参数:传出参数,需要传递一个整形数组的地址,数组大小为 2,也就是说最终会传出两个元素
    • pipefd[0]: 对应管道读端的文件描述符,通过它可以将数据从管道中读出
    • pipefd[1]: 对应管道写端的文件描述符,通过它可以将数据写入到管道中
  • 返回值:成功返回 0,失败返回 -1

进程间的通信

在讲解进程间通过管道的提醒具体内容之前,我们先来看一个简单的样例:

#include <iostream>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/types.h>using namespace std;int main()
{int fd[2] ;//定义两个文件描述符int ret=pipe(fd);  //创建管道if(ret==-1){perror("pipe error");}int pid=fork();  //创建子进程if(pid==0){close(fd[0]);/*这里子进程关闭读端,保留写端,这里我们希望将原来的在终端输出的内容改为输入到管道给父进程读取*/dup2(fd[1],STDOUT_FILENO);//将输出位置重定向到管道上execlp("ps","ps","aux",NULL);perror("execlp error");}else if(pid>0)  //执行父进程操作{close(fd[1]); //关闭写端char buff[1024];//读管道 //管道无数据——> read函数阻塞//管道有数据——> read停止阻塞(如果正处于阻塞状态),读取数据(若管道已满,写操作阻塞);while(true){sleep(5);memset(buff,0,sizeof(buff));int len=read(fd[0],buff,sizeof(buff));if(len==0)  cout<<"pipe is empty"<<endl;cout<<"buff:"<<buff<<" "<<"len:"<<len<<endl;}wait(NULL); //等待子进程结束回收资源}return 0;
}

备注

  • 子进程中执行shell命令相对于启动一个磁盘程序,因此需求使用execl()/execlp()函数
    • execlp(“ps”,“ps”,“aux”,NULL)
  • 子进程中执行完shell命令直接就可以终端输出结果,这些消息传递父进程?
    • 进程数据传递需要管道,子进程需要将数据写入管道,父进程需要从管道中读取数据
    • 这里子进程想将终端输出结果写入管道,因此需要将标准输出重定向到管道
    • 这里父进程要等待子进程执行完shell命令释放子进程资源进而避免僵尸进程,因此需要使用wait()函数

有名管道

有名管道和匿名管道类似,但是有名管道可以用于无亲缘关系的进程间通信,之所以叫有名管道,是因为它在磁盘上有一个文件,类型为p,它的大小为0,因为它的内容还是存储在
内存缓存区,但是我们打开它可以获取文件蛮舒服,进而基于它们我们可以实现无血缘关系进程之间的通讯,同时由于有名管道式一个文件实体,所以我们创建文件时渝新欧下面两种:

  • 基于shell命令创建
mkfifo filename
  • 基于C语言创建
#include<sys/types.h>
#include<sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
  • 参数
    • pathname:文件名
    • mode:权限
  • 返回值
    • 成功:0
    • 失败:-1

基于有名管道实现进程间通信

  • 写进程
// 有名管道的写端
#include <string>
#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <cstdio>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cerrno>
#include <cstdlib>
#include <string.h>using namespace std;int main()
{int wfd=open("./testfifo",O_WRONLY);if(wfd==-1){perror("open");return -1;}cout<<"open success"<<endl;int i=0;while(i<100){char str[1024];memset(str,0,sizeof(str));sprintf(str,"hello world %d\n",i);int wn=write(wfd,"hello world",strlen("hello world"));if(wn<0){cerr<<"错误码:"<<errno<<",错误原因:"<<strerror(errno)<<endl;break;}if(wn>0){cout<<"write "<<wn<<" bytes"<<endl;}i++;sleep(1);}close(wfd);return 0;
}
  • 读进程
#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <cstring>using namespace std;int main()
{int rfd = open("./testfifo", O_RDONLY);if (rfd == -1){perror("open");return -1;}char buf[1024];while (true){memset(buf, 0, sizeof(buf));int len = read(rfd, buf, sizeof(buf) - 1); // 减去1以防止覆盖结束符if (len >0)   cout<<"receive: "<<buf<<endl;}close(rfd); // 关闭文件描述符return 0;
}

管道描述符的修改

// 管道操作眼需要创建对应两个文件描述符, 分别是管道的读端和写端,但是创建完管道后也可以将它们对应的属性进行修改(比如将阻塞改为非阻塞),步骤如下:// 1. 获取读端的文件描述符的flag属性
int flag = fcntl(fd[0], F_GETFL);
// 2. 添加非阻塞属性到 flag中
flag |= O_NONBLOCK;
// 3. 将新的flag属性设置给读端的文件描述符
fcntl(fd[0], F_SETFL, flag);
// 4. 非阻塞读管道
char buf[4096];
read(fd[0], buf, sizeof(buf));

备注:虽然可以修改但是一般不建议这么做,这里涉及的仅供参考。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

如何利用 StarRocks 加速 Iceberg 数据湖的查询效率

数据湖作为一种存储各种类型数据的集中式存储系统&#xff0c;以其灵活性、可扩展性和低成本的优势受到越来越多企业的青睐。然而&#xff0c;数据湖虽然降低了数据存储成本&#xff0c;但在数据分析尤其是实时数据分析场景下&#xff0c;其性能仍存在一定瓶颈。 本文将探讨如何…

Python的异步编程

什么是协程&#xff1f; 协程不是计算机系统提供&#xff0c;程序员人为创造。 协程也可以被称为微线程&#xff0c;是一种用户态内的上下文切换技术。简而言之&#xff0c;其实就是通过一个线程实现代码块相互切换执行。 实现协程有那么几种方法&#xff1a; greenlet&…

Windows——解除Windows系统中文件名和目录路径的最大长度限制

第一步&#xff1a;打开本地组策略编辑器 按下Win R键打开运行窗口&#xff0c;输入 gpedit.msc 并回车&#xff0c;打开本地组策略编辑器。 第二步&#xff1a;开启 长路径设置 第三步&#xff1a;重启计算机

全新带货思路,用AI美女数字人做情感赛道,27天销量1559单

本期就另外分享一个全新的AI美女数字人带货思路&#xff0c;如果你正好对AI视频带货感兴趣&#xff0c;那么本期内容直接给你抹平“视频号上AI美女数字人玩法信息差”&#xff0c;最主要还是趁这类内容还不卷的时候&#xff0c;赶紧行动起来&#xff01; 更多实操教程和数字人工…

Paper解读:工作场所人机协作的团队形成:促进组织变革的目标编程模型

人工智能&#xff08;AI&#xff09;具有降低运营成本、提高效率和改善客户体验的潜力。 因此&#xff0c;在组织中组建项目团队至关重要&#xff0c;这样他们就会在决策过程中欢迎人工智能。 当前的技术革命要求公司快速变革&#xff0c;并增加了对团队在促进创新采用方面的作…

Chromium 屏蔽“缺少 Google API 密钥,因此 Chromium 的部分功能将无法使用。”提示 c++

新编译的Chromium工程默认gn参数如下: 可以利用gn args --list out/debug >1.txt 导出默认参数 google_api_key Current value (from the default) "" From //google_apis/BUILD.gn:43 Set these to bake the specified API keys and OAuth client …

【IT001】基于springboot+vue实现的在线问卷调查网站系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 项目描述 在当今信息爆炸的时代&#xff0c;数据收集与分析的重要…

经典文献阅读之--Stereo-NEC(全新双目VIO初始化)

0. 简介 双目VI-SLAM初始化方法分为两种类型&#xff1a;联合方法和分离方法。联合方法通过融合视觉观测和IMU积分来同时处理视觉和惯性参数&#xff0c;但有可能在闭合解中忽视陀螺仪偏置&#xff0c;而且计算成本高。分离方法首先独立解决SfM问题&#xff0c;然后根据纯视觉…

Qt --- 常用控件的介绍---Widget属性介绍

一、控件概述 编程&#xff0c;讲究的是站在巨人的肩膀上&#xff0c;而不是从头发明轮子。一个图形化界面上的内容&#xff0c;不需要咱们全都从零区实现&#xff0c;Qt中已经提供了很多内置的控件了&#xff08;按钮&#xff0c;文本框&#xff0c;单选按钮&#xff0c;复选…

CMake教程(八):添加定制命令和生成的文件

本篇继续 CMake 官网教程的第八篇教程&#xff0c;所用材料是 Step8 目录下的源代码。 本篇教程主要讲解如何通过 CMake 生成一个头文件&#xff0c;该头文件当中包含了 1 到 10 的平方根表格&#xff0c;然后在程序的其它部分包含这个生成的头文件。 出于教学的目的&#xf…

手机实时提取SIM卡打电话的信令声音-新的篇章(二、USB音频线初步探索)

手机实时提取SIM卡打电话的信令声音-新的篇章(二、USB音频线初步探索) 前言 前面的篇章和方案中,我们从架构拓扑和原理的角度分析了使用音频线来绕开手机对SIM卡电话的通话声音的封锁场景的可行性,并尝试拆分和对比模拟3.5mm耳机的音频和USB的数字音频线在使用上的差异。 在…

【ADC】系统误差分析中的统计原理

概述 本文学习于TI 高精度实验室课程&#xff0c;讨论典型和最大数据表规格的统计含义&#xff0c;分析最坏情况分析和查看典型值的统计分析之间的差异。 文章目录 概述一、最坏情况下的误差大小及其概率二、估计误差更好的方法 一、最坏情况下的误差大小及其概率 为了更好地…

【电机-概述及分类】

文章目录 第1章1-1 电机的定义1-2 电机的构成要素1-3 电机的分类1-3-1 直流电机1-3-1-1 永磁励磁型直流电机1-3-1-2 电磁铁励磁型直流电机 第1章 重新认识电机的体系 电机包括许多种类。换个角度来看&#xff0c;并没有完美的电机&#xff0c;某种电机具有所谓A的优点&#xf…

Unreal 对象、属性同步流程

文章目录 类型同步初始化创建 FObjectReplicator创建 FRepLayout、Cmd、ShadowOffset创建 FRepChangedPropertyTracker、FRepState创建 FReplicationChangelistMgr、FRepChangelistState、ShadowBuffer 属性同步属性变化检测查找变化属性&#xff0c;写入ShadowMemory发送数据 …

php email功能实现:详细步骤与配置技巧?

php email发送功能详细教程&#xff1f;如何使用php email服务&#xff1f; 无论是用户注册、密码重置&#xff0c;还是订单确认&#xff0c;电子邮件都是与用户沟通的重要手段。AokSend将详细介绍如何实现php email功能&#xff0c;并提供一些配置技巧&#xff0c;帮助你更好…

读代码UNET

这个后面这个大小怎么算的&#xff0c;这参数怎么填&#xff0c;怎么来的&#xff1f; 这是怎么看怎么算的&#xff1f; 这些参数设置怎么设置&#xff1f;卷积多大&#xff0c;有什么讲究&#xff1f;

65.【C语言】联合体

目录 目录 1.定义 2.格式 3.例题 答案速查 分析 4.练习 答案速查 分析 5.相同成员的联合体和结构体的对比 6.联合体的大小计算 2条规则 答案速查 分析 练习 答案速查 分析 7.联合体的优点 8.匿名联合体 1.定义 和结构体有所不同,顾名思义:所有成员联合使用同…

软件设计师——计算机网络

&#x1f4d4;个人主页&#x1f4da;&#xff1a;秋邱-CSDN博客☀️专属专栏✨&#xff1a;软考——软件设计师&#x1f3c5;往期回顾&#x1f3c6;&#xff1a;&#x1f31f;其他专栏&#x1f31f;&#xff1a;C语言_秋邱 一、OSI/ RM七层模型(⭐⭐⭐) ​ 层次 名称 主要功…

【STM32单片机_(HAL库)】4-1【定时器TIM】定时器中断点灯实验

1.硬件 STM32单片机最小系统LED灯模块 2.软件 timer驱动文件添加定时器HAL驱动层文件添加GPIO常用函数定时器中断配置流程main.c程序 #include "sys.h" #include "delay.h" #include "led.h" #include "timer.h"int main(void) {H…

latex打出邮箱图标和可点击的orcidID

如图所示&#xff1a; 邮箱的打法 \usepackage{bbding} \inst{(}\Envelope\inst{)}orcidID的打法 \newcommand{\myorcidID}[1]{\href{https://orcid.org/#1}{\includegraphics[width8pt]{res/orcid.png}}} \captionsetup[algorithm]{skip5pt} \definecolor{customblue}{RGB}{…