当前位置: 首页 > 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…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...