深入理解 Linux 管道:创建与应用详解(匿名管道进程池)

在现代操作系统中,进程间通信(IPC)是实现多任务、多进程协作的关键技术之一。Linux 提供了多种 IPC 机制,本博客将帮助您详细的理解进程间通信的原理

首先,在学习管道之前,我们先理解一下管道的存在是为了什么,顾名思义,是为了实现进程间的通信。而进程间的通信难道随随便便就可以进行某种交流了吗?显然是不可能的,所以我们讲

进程的通信也是需要某些协同的!所以协同的前提条件是什么呢? 是不是要先能够通信,通信的内容就是数据,数据间又是有类别的,所以要传递的不可能仅仅是数据还有它的相关属性!

那这就难办了,难办怎么办,wc那就别办,当然了进程可不像我们这么任性,难办归难办,还是得办,由于进程间是具有独立性的,进程 = 内核数据结构pcb + 代码数据

所以我们的第一个条件就来了,要想通信,我们是不是需要先让这些独立的进程之间可以看到一份共同的数据啊,你能看到我也能看到,你改动我也能看到,这不就完成初步通信了吗,可我们怎么能看到同一份资源呢,因为进程之间是独立的啊,他俩是不可能干这个事情了,这个时候我们的老大哥OS就来了,操作系统大哥说了:你们俩先别独立了,我这有个桥正好把你两家连上,你俩以后通信就在这通信,这OS发话谁敢不听,没办法,两个进程就这样完成了初步通信,

由上图可以看出,两个进程的通信都在同一个内核级文件缓冲区内,可是现在问题是,进程间的通信是需要成本的,而且成本还很高,那我操作系统的目的是什么,不就是让系统变的简单吗,那如何能缩减工作量呢?很简单--复用内核代码,所有就有了我们的两种管道--命名管道匿名管道 

1.匿名管道,也就是适用于具有血缘关系的进程,什么意思,父进程和子进程还有孙子进程,在我们之前讲子进程的时候知道父子进程之间是应用了写时拷贝技术的,大部分内容是浅拷贝的,因此这时我们采用的是匿名管道,那什么是管道呢?

管道顾名思义就是一端流入,一端流出,也就是单向通信,向我们平常打电话是不是你可以给对方说话,你说话的同时对方也能说话,这叫做双工通信,我们管道是一种特殊的半双工通信,什么意思呢,半双工通信就是你们之间是不能一起沟通的,这样会冲突,双方会听不清对方说的什么,可是它本质上还是支持你们互相说话的,我们特殊就特殊在它不支持互相说话,所以只能一端写,一端读,这样是不是就可以理解管道的通信了,那我们接下来了解一下管道的用法

#include<unistd.h>

int pipe(int fd[2]);

这个fd[2]是输出型参数,

pipe函数定义中的fd参数是一个大小为2的一个数组类型的指针。该函数成功时返回0,并将一对打开的文件描述符值填入fd参数指向的数组。失败时返回 -1并设置errno。

通过pipe函数创建的这两个文件描述符 fd[0] 和 fd[1] 分别构成管道的两端,往 fd[1] 写入的数据可以从 fd[0] 读出。并且 fd[1] 一端只能进行写操作,fd[0] 一端只能进行读操作,不能反过来使用。要实现双向数据传输,可以使用两个管道。

 也就是说我们的文件描述符数组中的文件描述符会作为输出参数,默认pipefd[0]是读,pipefd[1]是写端,此时我们的匿名管道也就完成了基础的构建,所以如何使用管道通信呢,就涉及到我们的代码构建

#include <iostream>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <string>
#include <vector>
#include <sys/types.h>
#include <sys/wait.h>
#include "task.hpp"
class Channel
{
public:Channel(int wfd, pid_t subprocesspid, std::string name): _wfd(wfd), _subprocesspid(subprocesspid), _name(name){}int getWfd() const{return _wfd;}pid_t getSubprocesspid() const{return _subprocesspid;}std::string getName() const{return _name;}// 形参类型和命名规范// const &: 输出// & : 输入输出型参数// * : 输出型参数//  task_t task: 回调函数void Wait(){int status;if (waitpid(_subprocesspid, &status, 0) == -1){std::cerr << "waitpid failed: " << strerror(errno) << std::endl;}if(waitpid(_subprocesspid, &status, 0) > 0){std::cout << "waitpid success" << std::endl;}if (WIFEXITED(status)){std::cout << _name << " exited with status " << WEXITSTATUS(status) << std::endl;}else{std::cerr << _name << " exited abnormally" << std::endl;}}void CloseChannel(){if (close(_wfd) == -1){std::cerr << "close " << _name << " failed: " << strerror(errno) << std::endl;}}private:int _wfd;pid_t _subprocesspid;std::string _name;
};void CreateChannelsandSubprocesses(int subprocessnum, std::vector<Channel> *channels, task_t task){for (int i = 0; i < subprocessnum; i++){int pipefd[2];if (pipe(pipefd) == -1){std::cerr << "pipe failed: " << strerror(errno) << std::endl;exit(1);}pid_t id = fork();if (id == -1){std::cerr << "fork failed:" << strerror(errno) << std::endl;}if (id == 0){if (i != 0){// 说明当前是第二个子进程for (int j = 0; j < i; j++){close((*channels)[j].getWfd());}}close(pipefd[1]);dup2(pipefd[0], STDIN_FILENO);task();close(pipefd[0]);exit(0);}close(pipefd[0]);channels->push_back(Channel(pipefd[1], id, "subprocess" + std::to_string(i)));}}int NextChannelIndex(int size){static int index = 0;return index++ % size;}void SendTask(int wfd, int tasknum){if (write(wfd, &tasknum, sizeof(tasknum)) == -1){std::cerr << "write failed: " << strerror(errno) << std::endl;}}void controlProcessonce(std::vector<Channel>& channels){int tasknum = Selecttask();int channel_index = NextChannelIndex(channels.size());SendTask(channels[channel_index].getWfd(), tasknum);}void controlProcess(std::vector<Channel>& channels,int times = -1){if(times > 0){while(times--){controlProcessonce(channels);}}else{while(1){controlProcessonce(channels);}}}void cleanupchannels(std::vector<Channel>& channels){for(auto& channel:channels){channel.CloseChannel();channel.Wait();}}
int main(int argc, char *argv[])
{if (argc < 2){std::cerr << "Usage:" << argv[0] << "subprocessnum" << std::endl;}int subprocessnum = atoi(argv[1]);if (subprocessnum <= 0){std::cerr << "subprocessnum must be greater than 0" << std::endl;}Loadtask();std::vector<Channel> channels;// 1. create subprocessnum subprocesses and establish communication channelsCreateChannelsandSubprocesses(subprocessnum, &channels, work1);// 2. control the subprocessescontrolProcess(channels, 10);// 3. close the channelscleanupchannels(channels);return 0;
}

大概看完以上代码的小伙伴就可以跟我进行下一步的验证了,这里时间有限,我们仅将实验过程中的代码出现的情况进行一个总结:

管道的四种情况:

1.如果管道内部是空的并且 write fd没有关闭,读取的条件就不具备,读进程就会堵塞,直到读取的条件具备之后也就是写入了数据才会进行读取

2.管道被写满并且 read fd不读且没有关闭,此时管道被写满了,写进程会被堵塞,直到读取后再写入

3.管道如果一直在读而写端突然关闭了wfd,那么read会返回0代表读到了文件结尾EOF

4.rfd直接关闭,可写端还在写入,那么此时OS会用13号信号关掉子进程,表示遇到异常。

5大特征:

1.匿名管道:只用来进行具有血缘关系的进程之间进行通信,常用于父子进程 

2.管道内部,自带进程之间同步的机制

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

4.管道文件在通信的时候是面向字节流的,write的次数和读取的次数不是一一匹配的

5.管道的通信模式是一种特殊的半双工模式 

到这我们就初步完成了匿名管道的学习,紧接着就是对于进程池的学习,我们的匿名管道正好是父子进程之间的通信,而如果我们有多个子进程,想让他们同时执行不同的任务,就需要我们的进程池了,既可以完成父子间的通信,还可以完成对不同任务的分发,从而显著减少进程创建和销毁的开销,提升系统性能和响应速度。请看下一篇博客哦 

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

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

相关文章

SWM221系列芯片之电机应用及控制

经过对SWM221系列的强大性能及外设资源&#xff0c;TFTLCD彩屏显示及控制进行了整体介绍后&#xff0c;新迎来我们的电控篇---SWM221系列芯片之电机应用及控制。在微控制器市场面临性能、集成度与成本挑战的当下&#xff0c;SWM221系列芯片以其卓越性能与创新设计&#xff0c;受…

Trimble天宝X9三维扫描仪为建筑外墙检测提供了全新的解决方案【沪敖3D】

随着城市化进程的快速推进&#xff0c;城市高层建筑不断增多&#xff0c;对建筑质量的要求也在不断提高。建筑外墙检测&#xff0c;如平整度和垂直度检测&#xff0c;是衡量建筑质量的重要指标之一。传统人工检测方法不仅操作繁琐、效率低下&#xff0c;还难以全面反映墙体的真…

机器人手眼标定

机器人手眼标定 一、机器人手眼标定1. 眼在手上标定基本原理2. 眼在手外标定基本原理 二、眼在手外标定实验三、标定精度分析 一、机器人手眼标定 要实现由图像目标点到实际物体上抓取点之间的坐标转换&#xff0c;就必须拥有准确的相机内外参信息。其中内参是相机内部的基本参…

unity中的UI系统---GUI

一、工作原理和主要作用 1.GUI是什么&#xff1f; 即即时模式游戏用户交互界面&#xff08;IMGUI&#xff09;&#xff0c;在unity中一般简称为GUI&#xff0c;它是一个代码驱动的UI系统。 2.GUI的主要作用 2.1作为程序员的调试工具&#xff0c;创建游戏内调测试工具 2.2为…

Java开发 PDF文件生成方案

业务需求背景 业务端需要能够将考试答卷内容按指定格式呈现并导出为pdf格式进行存档&#xff0c;作为紧急需求插入。导出内容存在样式复杂性&#xff0c;包括特定的字体&#xff08;中文&#xff09;、字号、颜色&#xff0c;页面得有页眉、页码&#xff0c;数据需要进行表格聚…

SpringCloud微服务架构

文章目录 认识微服务&#xff1a;SpringCloud 服务拆分及远程调用实现夸远程服务调用使用RestTemplateEureka注册中心 搭建EruekaServer注册服务服务发现 Ribbon负载均衡 修改负载均衡规则解饿加载 Nacos注册中心&#xff08;nacos一部分功能&#xff09; 服务注册到nacosnacos…

【设计模式-02】23 种设计模式的分类和功能

在软件工程领域&#xff0c;设计模式是解决常见设计问题的经典方案。1994 年&#xff0c;Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides&#xff08;四人帮&#xff0c;GoF&#xff09;在《设计模式&#xff1a;可复用面向对象软件的基础》一书中系统性地总结了…

简历_专业技能_熟悉分布式锁Redisson的原理以及使用

系列博客目录 文章目录 系列博客目录怎么样才能够在简历上写熟悉redisson的应用以及原理1. 清晰描述技能与经验示例&#xff1a; 2. 列举具体应用场景示例项目经验&#xff1a; 3. 展示你对原理的理解示例&#xff1a; 4. 用简历中的关键词突出你的能力示例段落&#xff1a; 5.…

分布式任务调度xxl-job入门案例

XXL-JOB是一个分布式任务调度平台&#xff0c;简单来说就是可以在你指定的时间内调用某个功能&#xff0c;就例如购物某个商品的限时抢购从什么时候开始以及结束抢购类似于这样的。 下面是它的一个仓库地址 http://gitee.com/xuxueli0323/xxl-job 下载之后将项目导入进idea中&…

瑞芯微rk3566刷机流程(黑豹X2)

文章目录 概要 刷机方式 卡刷流程 线刷流程 小结 概要 记录rk3566刷机的过程&#xff0c;纯纯的小白&#xff0c;艰难而有意义的一天。 刷机方式 1、卡刷&#xff08;tf卡&#xff09; 2、线刷&#xff08;双公头usb线&#xff09; 卡刷流程 1、下载armbian镜像 1、…

计算机网络——数据链路层-流量控制和可靠传输

一、流量控制 流量控制是指由接收方及时控制发送方发送数据的速率&#xff0c;使接收方来得及接受。 • 停止等待流量控制 • 滑动窗口流量控制 1、停止—等待流量控制 停止-等待流量控制的基本原理是发送方每发出一帧后&#xff0c;就要等待接收方的应答信号&#xff…

GPT系统重大升级,开创国内先河:o1支持图片识别功能正式上线

文章目录 零、前言一、授权码登录体验优化&#xff1a;一步直达聊天界面二、全新“项目”功能&#xff1a;让工作更有条理三、语音功能升级&#xff1a;全新交互体验四、o1支持图片识别五、总结 零、前言 我是虚竹哥&#xff0c;目标是带十万人玩转ChatGPT。 亲爱的用户&…

RabbitMQ-基本使用

RabbitMQ: One broker to queue them all | RabbitMQ 官方 安装到Docker中 docker run \-e RABBITMQ_DEFAULT_USERrabbit \-e RABBITMQ_DEFAULT_PASSrabbit \-v mq-plugins:/plugins \--name mq \--hostname mq \-p 15672:15672 \-p 5672:5672 \--network mynet\-d \rabbitmq:3…

弹性云服务器ECS“规格”

规格详细资料&#xff1a;规格清单&#xff08;x86&#xff09;_弹性云服务器 ECS_华为云 通用计算型 各规格详细介绍请参见通用计算型。 规格名称 计算 磁盘类型 网络 通用计算型X1 CPU/内存配比&#xff1a;自定义vCPU数量范围&#xff1a;1-16处理器&#xff1a;第三…

Java SpringBoot使用Apache POI导入导出Excel文件

点击下载《Java SpringBoot使用Apache POI导入导出Excel文件(源代码)》 1. Apache POI 简介 Apache POI 是一个强大的 Java 库&#xff0c;用于处理 Microsoft Office 文档&#xff0c;包括 Excel 文件&#xff08;.xls 和 .xlsx&#xff09;。在 Java Spring Boot 项目中&am…

在 macOS 中,设置自动将文件夹排在最前

文章目录 1、第一步访达设置2、第二步排序方式 需要两步设置 1、第一步访达设置 按名称排序的窗口中 2、第二步排序方式 选择名称

汇编环境搭建

学习视频 将MASM所在目录 指定为C盘

Sentinel-5P遥感数据下载及预处理教程【20250105】

Sentinel-5P是欧空局&#xff08;Europe Space Agency&#xff0c;ESA&#xff09;于2017年10月13日发射的一颗全球大气污染监测卫星。卫星搭载了对流层观测仪&#xff08;Tropospheric Monitoring Instrument&#xff0c;TROPOMI&#xff09;&#xff0c;可以有效的观测全球各…

java项目之高校心理教育辅导系统的设计与实现(springboot+mybatis+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的闲一品交易平台。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 高校心理教育辅导系统的设…

打造三甲医院人工智能矩阵新引擎(一):文本大模型篇--基于GPT-4o的探索

一、引言 当今时代,人工智能技术正以前所未有的速度蓬勃发展,深刻且广泛地渗透至各个领域,医疗行业更是这场变革的前沿阵地。在人口老龄化加剧、慢性疾病患病率上升以及人们对健康需求日益增长的大背景下,三甲医院作为医疗体系的核心力量,承担着极为繁重且复杂的医疗任务。…