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

【Linux-进程间通信】匿名管道+4种情况+5种特征

匿名管道

匿名管道(Anonymous Pipes)是Unix和类Unix操作系统中的一种通信机制,用于在两个进程之间传递数据。匿名管道通常用于命令行工具之间的数据传递;

匿名管道的工作原理是创建一个临时文件,该文件被称为管道文件,它仅存在于内存中,不持久化到磁盘。当一个进程创建一个匿名管道时,它会打开一个写入端和一个读取端。写入端通常由|运算符创建,而读取端则通过<运算符

匿名管道的一个关键特性是它是单向的,即只能从写入端到读取端传递数据。此外,一旦管道中的数据被读取,管道就会被关闭,不能再次使用。

【问题1】如果我想双向通信呢?两个管道

【问题2】为什么要单向通信?为了简单,因为我们想要单向通信,使用我们叫它管道

pipe

在C语言中,pipe函数是用于创建一个匿名管道(也称为管道)的标准库函数。它允许进程之间通过管道进行通信。pipe函数的声明如下:

 

这个函数的作用是在调用进程和其子进程之间创建一个匿名管道。pipefd是一个整数数组,包含两个整数元素,分别用于读取和写入管道。

  • pipefd[0]:这是管道的读取端,可以通过它从管道中读取数据。

  • pipefd[1]:这是管道的写入端,可以通过它将数据写入管道。

pipe函数的返回值:

  • 如果成功,pipe函数返回0。

  • 如果失败,pipe函数返回-1,并设置errno以指示错误。

成功调用pipe函数后,返回的两个文件描述符pipefd[0]pipefd[1]可以用于后续的读取和写入操作。

从上图可以看出,当需要进行通信时,需要通过pipefd[1]文件描述符,将数据拷贝到管道文件中;再通过pipefd[0]文件描述符,将管道文件中的数据拷贝到用户空间中。因而,管道通信时,需要产生两次拷贝

我们简单测试一下返回的文件描述符

testpipe.cc

#include <iostream>
#include <string>
#include <cerrno>  // errno.h
#include <cstring> // string.h
#include <unistd.h>int main(){//1.创建管道int pipefd[2];int n = pipe(pipefd);//输出型参数,rfd,wfdif(n != 0){std::cerr << "errno: " << errno << ": "<< "errstring : " << strerror(errno) << std::endl;return 1;}std::cout << "pipefd[0]: " << pipefd[0] << ", pipefd[1]: " << pipefd[1] << std::endl;return 0;
}

 

 接下来让子进程写入数据,父进程读数据,在此期间会关闭不需要的fd

#include <iostream>
#include <string>
#include <cerrno>  // errno.h
#include <cstring> // string.h
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>const int size = 1024;
std::string getOtherMessage()
{static int cnt = 0;std::string messageid = std::to_string(cnt); // stoi -> string -> intcnt++;pid_t self_id = getpid();std::string stringpid = std::to_string(self_id);std::string message = "messageid: ";message += messageid;message += " my pid is : ";message += stringpid;return message;
}// 子进程进行写入
void SubProcessWrite(int wfd)
{int pipesize = 0;std::string message = "father, I am your son prcess!";char c = 'A';while (true){std::string info = message + getOtherMessage(); // 这条消息,就是我们子进程发给父进程的消息write(wfd, info.c_str(), info.size()); // 写入管道的时候,没有写入\0, 有没有必要?没有必要std::cerr << info << std::endl;sleep(2); // 子进程写慢一点// write(wfd, &c, 1);// std::cout << "pipesize: " << ++pipesize << " write charator is : "<< c++ << std::endl;// // if(c == 'G') break;// sleep(1);}std::cout << "child quit ..." << std::endl;
}// 父进程进行读取
void FatherProcessRead(int rfd)
{char inbuffer[size]; // c99 , gnu g99while (true){//sleep(2);std::cout << "-------------------------------------------" << std::endl;// sleep(500);ssize_t n = read(rfd, inbuffer, sizeof(inbuffer) - 1); // sizeof(inbuffer)->strlen(inbuffer);if (n > 0){inbuffer[n] = 0; // == '\0'std::cout  << inbuffer << std::endl;}else if (n == 0){// 如果read的返回值是0,表示写端直接关闭了,我们读到了文件的结尾std::cout << "client quit, father get return val: " << n << " father quit too!" << std::endl;break;}else if(n < 0){std::cerr << "read error" << std::endl;break;}// sleep(1);break;}
}int main(){//1.创建管道int pipefd[2];int n = pipe(pipefd);//输出型参数,rfd,wfdif(n != 0){std::cerr << "errno: " << errno << ": "<< "errstring : " << strerror(errno) << std::endl;return 1;}std::cout << "pipefd[0]: " << pipefd[0] << ", pipefd[1]: " << pipefd[1] << std::endl;// 2. 创建子进程pid_t id = fork();if (id == 0){std::cout << "子进程关闭不需要的fd了, 准备发消息了" << std::endl;sleep(1);// 子进程 --- write// 3. 关闭不需要的fdclose(pipefd[0]);SubProcessWrite(pipefd[1]);close(pipefd[1]);exit(0);}// 3. 父进程读入数据// 关闭不需要的fdclose(pipefd[1]);FatherProcessRead(pipefd[0]);std::cout << "5s, father close rfd" << std::endl;sleep(5);close(pipefd[0]);int status = 0;pid_t rid = waitpid(id, &status, 0);if (rid > 0){std::cout << "wait child process done, exit sig: " << (status&0x7f) << std::endl;std::cout << "wait child process done, exit code(ign): " << ((status>>8)&0xFF) << std::endl;}return 0;
}

管道的四种情况 和5种特征

【特征一】匿名管道:只能用来进行具有血缘关系的进程之间,进行通信,常用于父子进程之间通信

【情况1️⃣】如果管道内部是空的 并且 write fd没有关闭,读取条件不具备,读进程会被阻塞,解决方案,等待读取条件具备,也就是写入数据

【特征二】管道内部,自带进程之间同步的机制-->多执行流执行代码的时候,具有明显的顺序性

我们让子进程写慢一点,父进程持续去读

 

 

观察到的现象就是,每隔5秒打印一次,也就是父进程读取要和子进程一致,子进程慢了,父进程就要读慢点,子进程写一条,父进程读一条;在5s期间,父进程就在等待子进程写数据,也就是读进程被阻塞

【情况2️⃣】管道被写满,并且父进程不读且不关闭;管道被写满会被阻塞,如果要恢复正常就需要父进程读取数据(让写条件具备)

我们接下来让子进程疯狂写入,父进程不读,也就是给父进程休眠500s观察情况

 

现象就是子进程写到第65536就一直卡在哪里,我们父进程一直在,但是不读,这里我们也就可以计算出管道文件的大小65536/1024 = 64kb,也就是ubuntu下22.04管道大小是64kb

子进程写满之后就会被阻塞

【情况3️⃣】管道一直在读但是写端关闭了,读端read返回值会读到0,表示读到了文件结尾

我们让子进程写一条就关闭,父进程一直去读

 这样读端就会返回0,表示读到了文件结尾

【情况4️⃣】读端直接关闭,写端一直写入-->写端进程会被操作系统直接使用13号信号关掉,相当于进程出现了异常

 

【特征三】管道文件的生命周期是随进程的

【特征四】管道文件在通信的时候,是面向字节流的,写入的次数和读取的次数不是一一匹配的

如何理解特征四?

面向字节流:管道文件在通信时,数据是以字节为单位进行传输的。这意味着写入端可以一次写入多个字节,而读取端可以一次读取多个字节,或者可以分多次读取。

写入次数和读取次数不是一一匹配的:由于管道是半双工的,写入端和读取端的数据传输不是同步进行的。这意味着,写入端可能已经写入了多个字节,而读取端还没有开始读取,或者读取端已经读取了部分数据,而写入端还在继续写入。

数据传输是异步的:管道通信是异步的,这意味着写入端和读取端之间的数据传输不一定是连续的。写入端可以写入数据,然后继续执行其他操作,而读取端可以等待数据准备好后再读取。

数据缓冲:管道内部通常有一个缓冲区,用于存储写入端写入的数据。当读取端开始读取时,它会从缓冲区中读取数据。如果缓冲区满了,写入端可能会阻塞,直到有空间可用。如果缓冲区空了,读取端可能会阻塞,直到有数据可读。

管道通信的完整性:尽管写入次数和读取次数不是一一匹配的,但管道通信的完整性得到了保证。写入端写入的数据最终会被读取端读取,反之亦然。

【特征五】管道的通信模式,是一种特殊的半双工模式

在计算机网络和通信领域,半双工(Half-Duplex)和全双工(Full-Duplex)是描述通信设备或通道能否同时进行双向通信的术语。

半双工(Half-Duplex)

  • 半双工通信是指通信的双方可以交替地发送和接收数据,但不能同时进行。

  • 举个例子,对讲机就是半双工的,当一方正在说话时,另一方必须等待,不能同时说话。

  • 在半双工模式下,通信通道的带宽利用率较低,因为一方在发送数据时,另一方无法发送数据。

全双工(Full-Duplex)

  • 全双工通信是指通信的双方可以同时发送和接收数据,就像电话通话一样。

  • 在全双工模式下,通信通道的带宽利用率较高,因为双方可以同时进行通信,而不需要等待。

  • 全双工通常需要两个独立的通信通道,例如两个独立的物理线路,或者一个物理线路上的两个独立的逻辑通道。

总结来说,半双工通信需要轮流发送和接收数据,而全双工通信可以同时进行双向通信。全双工通信通常更高效,因为它允许多个设备或通道同时工作,而不需要等待。

相关文章:

【Linux-进程间通信】匿名管道+4种情况+5种特征

匿名管道 匿名管道&#xff08;Anonymous Pipes&#xff09;是Unix和类Unix操作系统中的一种通信机制&#xff0c;用于在两个进程之间传递数据。匿名管道通常用于命令行工具之间的数据传递&#xff1b; 匿名管道的工作原理是创建一个临时文件&#xff0c;该文件被称为管道文件…...

Perl打印9x9乘法口诀

本章教程主要介绍如何用Perl打印9x9乘法口诀。 一、程序代码 1、写法① use strict; # 启用严格模式&#xff0c;帮助捕捉变量声明等错误 use warnings; # 启用警告&#xff0c;帮助发现潜在问题# 遍历 1 到 9 的数字 for my $i (1..9) {# 对于每个 $i&#xff0c;遍历 1…...

Android--第一个android程序

写在前边 ※安卓开发工具常用模拟器汇总Android开发者必备工具-常见Android模拟器(MuMu、夜神、蓝叠、逍遥、雷电、Genymotion...)_安卓模拟器-CSDN博客 ※一般游戏模拟器运行速度相对较快&#xff0c;本文选择逍遥模拟器_以下是Android Studio连接模拟器实现(先从以上博文中…...

MySQL的并行复制原理

1. 并行复制的概念 并行复制&#xff08;Parallel Replication&#xff09;是一种通过同时处理多个复制任务来加速数据复制的技术。它与并发复制的区别在于&#xff0c;并行复制更多关注的是数据块或事务之间的并行执行&#xff0c;而不是单纯的任务并发。在数据库主从复制中&…...

2023年五一杯数学建模C题双碳目标下低碳建筑研究求解全过程论文及程序

2023年五一杯数学建模 C题 双碳目标下低碳建筑研究 原题再现&#xff1a; “双碳”即碳达峰与碳中和的简称&#xff0c;我国力争2030年前实现碳达峰&#xff0c;2060年前实现碳中和。“双碳”战略倡导绿色、环保、低碳的生活方式。我国加快降低碳排放步伐&#xff0c;大力推进…...

信息安全工程师(57)网络安全漏洞扫描技术与应用

一、网络安全漏洞扫描技术概述 网络安全漏洞扫描技术是一种可以自动检测计算机系统和网络设备中存在的漏洞和弱点的技术。它通过使用特定的方法和工具&#xff0c;模拟攻击者的攻击方式&#xff0c;从而检测存在的漏洞和弱点。这种技术可以帮助组织及时发现并修补漏洞&#xff…...

练习题 - Scrapy爬虫框架 Spider Middleware 爬虫页中间件

在 web 爬虫开发中,Scrapy 是一个非常强大且灵活的框架,它可以帮助开发者轻松地从网页中提取数据。Scrapy 的下载器中间件(Downloader Middleware)是 Scrapy 处理下载请求和响应的一个重要组件。通过使用和编写下载器中间件,开发者可以自定义请求的处理过程,增加请求头信…...

探索C++的工具箱:双向链表容器类list(1)

引言 在C中&#xff0c;std::list 是一个标准库提供的容器类&#xff0c;属于C STL&#xff08;标准模板库&#xff09;。std::list 是一种独特而强大的容器&#xff0c;它使用双向链表结构来管理元素。无论是在处理动态数据集合&#xff0c;还是在需要频繁进行插入和删除操作时…...

大厂高频算法考点--单调栈

什么是单调栈&#xff1a; 单调栈就是借助一个栈&#xff0c;在仅仅使用当前栈的条件下&#xff0c;时间复杂度是N&#xff08;n&#xff09;,将每个节点最有离这他最近的大于或者是小于的数据返回&#xff0c;将已知数组的元素放到栈里。再自我实现的代码里面我们使用数组实现…...

Unity使用Git及GitHub进行项目管理

git: 工作区,暂存区(存放临时要存放的内容),代码仓库区1.初始化 git init 此时展开隐藏项目,会出现.git文件夹 2.减小项目体积 touch .gitignore命令 创建.gitignore文件夹 gitignore文件夹的内容 gitignore中添加一下内容 # This .gitignore file should be place…...

如何将本地 Node.js 服务部署到宝塔面板:完整的部署指南

文章简介&#xff1a; 将本地开发的 Node.js 项目部署到线上服务器是开发者常见的工作流程之一。在这篇文章中&#xff0c;我将详细介绍如何将本地的 Node.js 服务通过宝塔面板&#xff08;BT 面板&#xff09;上线。宝塔面板是一个强大的服务器管理工具&#xff0c;具有简洁的…...

SpringBoot项目启动报错:命令行太长解决

文章目录 SpringBoot项目启动报错&#xff1a;命令行太长解决1. 第一种方法1. 第二种方法1-1 旧版本Idea1-2 新版本Idea 3. 重新启动SpringBoot项目即可解决 SpringBoot项目启动报错&#xff1a;命令行太长解决 报错信息&#xff1a; 1. 第一种方法 1. 第二种方法 找到项目…...

使用Docker启动的Redis容器使用的配置文件路径等问题以及Python使用clickhouse_driver操作clickhouse数据库

一、使用Docker启动的Redis容器使用的配置文件路径等问题 1.docker启动的redis使用的配置文件路径是什么 使用docker搭建redis服务&#xff0c;本身redis启动的时候可以指定配置文件的&#xff0c; redis-server /指定配置文件路径/redis.conf。 但手上也没有一个redis配置文件…...

硬盘格式化后能恢复数据吗?4款好用的数据恢复软件,格式化后也能安心

咱们今天来谈谈一个挺烦人的问题——硬盘格式化后能恢复数据吗&#xff1f;别担心&#xff0c;能的&#xff01;只要你用对方法&#xff0c;就算硬盘被清空了&#xff0c;那些重要文件还是能找回来的。下面&#xff0c;我就给你们介绍几款超给力的数据恢复软件&#xff0c;让你…...

【选择C++游戏开发技术】

在选择C游戏开发技术时&#xff0c;以下几个因素是需要考虑的&#xff1a; 1. 游戏类型&#xff1a;不同类型的游戏可能需要不同的技术。例如&#xff0c;2D游戏通常采用基于精灵的引擎&#xff0c;而3D游戏通常采用基于物理模拟的引擎。根据游戏类型选择适合的技术是很重要的…...

Oracle数据库系统表空间过大,清理SYSTEM、SYSAUX表空间

一.前言 在oracle数据库中&#xff0c;system为系统表空间&#xff0c;存放着一些我们经常用到的系统表和视图&#xff0c;sysaux为辅助表空间&#xff0c;辅助着系统表空间。这两个表空间不宜添加数据文件&#xff0c;会使系统表空间过于臃肿&#xff0c;从而影响数据库的使用…...

LaTeX参考文献工具和宏包bibmap项目简介

LaTeX参考文献工具和宏包bibmap项目简介 LaTeX 中的参考文献生成方式主要有三种&#xff1a;第一种是手动写thebibliography环境的&#xff0c;第二种事基于bibtex程序的&#xff0c;第三种则是基于biblatex宏包和biber程序的。本文介绍的bibmap项目则提供了第四种方法。目前b…...

微软的 Drasi:一种轻量级的事件驱动编程方法

微软的开源数据变化处理平台有望提供一种全新的方式来构建和管理可产生持续事件流的云应用程序。 Microsoft Azure 孵化团队是微软超大规模云中比较有趣的组成部分之一。它介于传统软件开发团队和研究组织之间&#xff0c;致力于构建大规模分布式系统问题的解决方案。 这些解决…...

vue3 笔记-插槽

结构类似的模块&#xff0c;我们可以考虑用插槽&#xff0c;以便后续复用&#xff1a; 代码&#xff1a; 1.插槽 <script setup> defineProps({title: {required: true,type: String},number: {required: true,type: Number} }) </script><template><d…...

C# 字符串常用方法

文章目录 Length&#xff1a;获取字符串中字符的个数&#xff08;不包括末尾的空字符&#xff09;ToLower() 和 ToUpper()&#xff1a;将字符串转换为小写或大写形式Substring(int startIndex, int length)&#xff1a;从指定索引开始截取指定长度的子字符串Remove(int startIn…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...