linux——进程间通信及管道的应用场景

linux进程的控制-CSDN博客

liunx——进程间通信(管道通信)-CSDN博客


文章目录

文章目录

前言

二、管道的应用

1.创建子进程

1、描述:

2.创建进程及管理

3、子进程接受任务

4、控制子进程

总结


前言

 上篇博客我们学习了进程间通信,并且我们还写了一个简单的进程间的通信,实现了子进程写数据父进程读数据。


管道的特征:

1、具有血缘关系的进程进行进程间通信;

2、管道只能单向通信;

3、父子进程是会进程协同的,同步与互斥的——保护管道文件的数据安全

4、管道是面向字节流的;

5、管道是基于文件的,而文件的生命周期吃随进程的!

一、进程间通信的四种情况

a:读写端正常,管道如果为空,读端就堵塞;

模拟:

void Write(int rfd)
{char buff[1024];//string s="hello word!!";int count=0;while(true){   //snprintf(buff,sizeof(buff),"%s - %d - %d ",s.c_str(),getpid(),count);//write(rfd,buff,sizeof(buff));count++;sleep(1);if(count==5){break;}}}
void Read(int rfd)
{int count=0;char buff[1024]={0};while(true){int n = read(rfd,buff,sizeof(buff));count++;sleep(1);if(count==10){printf("father read file done!\n");break;}cout << "father get a message[" << getpid() << "]# " << buff << endl;}
}

读数据10秒,写数据为空,不想管道写入数据那么管道就是空的,此时读端阻塞,等写端关闭,父进程继续;

 

b:读写端正常,管道如果被写满了,写端就会堵塞;

void Write(int rfd)
{char buff[1024];char bu[1]={'c'};string s="hello word!!";int count=0;int size=0;int t=0;while(true){   cout<<size<<endl;//snprintf(buff,sizeof(buff),"%s - %d - %d ",s.c_str(),getpid(),count);//int n =write(rfd,buff,sizeof(buff));int n =write(rfd,bu,sizeof(bu));size+=n;//count++;//sleep(1);if(n==0){sleep(5);cout<<"写文件最大内容size "<<size<<endl;t=size;break;//写满了不退}}}
void Read(int rfd)
{int count=0;char buff[1024000]={0};while(true){//int n = read(rfd,buff,sizeof(buff));count++;sleep(1);if(count==5){int n = read(rfd,buff,sizeof(buff));cout << "father get a message[" << getpid() << "]# " << buff << endl;cout<<n<<endl;printf("father read file done!\n");break;}// cout << "father get a message[" << getpid() << "]# " << buff << endl;}
}

因为读端一直不读,写端写满了就阻塞在了write那里,所以在写端打印的计数只能到65536处就阻塞了,打印不出来65536,而读端一次可以把管道的全读完。

而65569是读端将管道读完以后,管道空了,写端又开始写了。

c:读端正常读,写端关闭,读端就会读到0,表面读到了文件结尾,不会被阻塞;

void Write(int rfd)
{char buff[1024];string s="hello word!!";int count=0;int size=0;int t=0;while(true){   snprintf(buff,sizeof(buff),"%s - %d - %d ",s.c_str(),getpid(),count);int n =write(rfd,buff,sizeof(buff));count++;sleep(1);if(count==5){break;//写满了不退}}}
void Read(int rfd)
{int count=0;char buff[1024];while(true){buff[0]=0;int n = read(rfd,buff,sizeof(buff));if(n>0)buff[n]='\0';count++;sleep(1);if(count==10){printf("father read file done!\n");break;}cout << "father get a message[" << getpid() << "]# " << buff << endl;}
}

d:写端正常写,读端关闭;操作系统就要就要杀掉正在写入的进程。

void Write(int rfd)
{char buff[1024];string s="hello word!!";int count=0;int size=0;int t=0;while(true){   snprintf(buff,sizeof(buff),"%s - %d - %d ",s.c_str(),getpid(),count);int n =write(rfd,buff,sizeof(buff));count++;sleep(1);if(n==0){break;//写满了不退}}}
void Read(int rfd)
{int count=0;char buff[1024];while(true){buff[0]=0;int n = read(rfd,buff,sizeof(buff));if(n>0)buff[n]='\0';count++;sleep(1);if(count==5){printf("father read file done!\n");break;}cout << "father get a message[" << getpid() << "]# " << buff << endl;}
}

二、管道的应用

实现一个向多个进程发送指令;

1.创建子进程

我们在前面的学习过程中,我们知道了操作系统在管理进程的时候是对我们的进程,还有文件等等都是先描述在组织;

那么我们就创建一批进程将他们管理起来。

1、描述:

class channel
{
public:channel(int cmdfd, int slaverid, const std::string &processname):_cmdfd(cmdfd), _slaverid(slaverid), _processname(processname){}
public:int _cmdfd;               // 发送任务的文件描述符pid_t _slaverid;          // 子进程的PIDstd::string _processname; // 子进程的名字 -- 方便我们打印日志// int _cmdcnt;
};

2.创建进程及管理

void InitProcessPool(std::vector<channel> *channels)
{for(int i=0;i<processnum;i++){int pipefd[2]={0};int n=pipe(pipefd);assert(!n); (void)n;    pid_t id=fork();if(id<0){perror("fork\0");return ;}if(id==0){//子进程读close(pipefd[1]);dup2(0,pipefd[0]);//将写文件重载到键盘位slaver();//子进程接受指令close(0);}//父进程将文件组织起来close(pipefd[0]);//给子进程命名string name="process-" + std::to_string(i);channels->push_back(channel(pipefd[1],id,name));sleep(1);}
}

这段初始化就是创建一批进程将这批进程管理起来,而这些进程也都是一些管道和父进程连接在一起的;

3、子进程接受任务

void slaver()
{// read(0)while(true){int cmdcode = 0;int n = read(0, &cmdcode, sizeof(int)); // 如果父进程不给子进程发送数据呢??阻塞等待!if(n == sizeof(int)){//执行cmdcode对应的任务列表std::cout <<"slaver say@ get a command: "<< getpid() << " : cmdcode: " <<  cmdcode << std::endl;if(cmdcode >= 0 && cmdcode < tasks.size()) tasks[cmdcode]();}if(n == 0) break;}
}

我们知道我们管道传输的数据越大,那么效率越低,那么我就传输一个整数,然后通过这个整数去调取函数数组的函数;

我们进程子进程通过管道读取到父进程发送的指令,然后将我们的整数当下标去调用函数。

4、控制子进程

给出目录

void Menu()
{std::cout << "################################################" << std::endl;std::cout << "# 1. 刷新日志             2. 刷新出来野怪        #" << std::endl;std::cout << "# 3. 检测软件是否更新      4. 更新用的血量和蓝量  #" << std::endl;std::cout << "#                         0. 退出               #" << std::endl;std::cout << "#################################################" << std::endl;
}
void ctrlSlaver(const std::vector<channel> &channels)
{int which = 0;//用来选择进程while(true){int select = 0;//用来选择执行什么指令Menu();std::cout << "Please Enter@ ";std::cin >> select;if(select <= 0 || select >= 5) break;//不在指令内就退出// select > 0&& select < 5// 1. 选择任务int cmdcode = select - 1;//我们的进程的cmdfd从channels的0号下标开始存储,选项是1// 2. 选择进程std::cout << "father say: " << " cmdcode: " <<cmdcode << " already sendto " << channels[which]._slaverid << " process name: " << channels[which]._processname << std::endl;// 3. 发送任务write(channels[which]._cmdfd, &cmdcode, sizeof(cmdcode));which++;which %= channels.size();}
}

 我们只需要向子进程通过管道传输我们目录中给出的选项就可以选择让子进程执行什么了。

5、清理收尾

void QuitProcess(const std::vector<channel> &channels)
{for(const auto &c : channels){close(c._cmdfd);waitpid(c._slaverid, nullptr, 0);}
}

将我们的连接管道端关闭,然后让父进程将自己一个一个回收掉;


总结

管道的特征:

1、具有血缘关系的进程进行进程间通信;

2、管道只能单向通信;

3、父子进程是会进程协同的,同步与互斥的——保护管道文件的数据安全

4、管道是面向字节流的;

5、管道是基于文件的,而文件的生命周期吃随进程的!

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

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

相关文章

FPGA实现串口升级及MultiBoot(十)串口升级SPI FLASH实现

本文目录索引 工程架构example9工程设计Vivado设计Vitis设计example9工程验证1、读取FLASH ID2、擦除整个FLASH3、Blank-Check4、烧写Golden区位流5、读取FLASH内容6、烧写MultiBoot区位流(升级位流)7、MultiBoot区位流(升级位流)启动example10工程设计Vivado设计Vitis设计exam…

AIGC引领金融大模型革命:未来已来

文章目录 金融大模型的应用场景1. **金融风险管理**2. **量化交易**3. **个性化投资建议**4. **金融欺诈检测和预防**5. **智能客户服务** 金融大模型开发面临的挑战应对策略《金融大模型开发基础与实践》亮点内容简介作者简介获取方式 在AIGC&#xff08;Artificial Intellige…

设计模式学习[10]---迪米特法则+外观模式

文章目录 前言1. 迪米特法则2. 外观模式2.1 原理阐述2.2 举例说明 总结 前言 之前有写到过 依赖倒置原则&#xff0c;这篇博客中涉及到的迪米特法则和外观模式更像是这个依赖倒置原则的一个拓展。 设计模式的原则嘛&#xff0c;总归还是高内聚低耦合&#xff0c;下面就来阐述…

BWO-CNN-BiGRU-Attention白鲸优化算法优化卷积神经网络结合双向门控循环单元时间序列预测,含优化前后对比

BWO-CNN-BiGRU-Attention白鲸优化算法优化卷积神经网络结合双向门控循环单元时间序列预测&#xff0c;含优化前后对比 目录 BWO-CNN-BiGRU-Attention白鲸优化算法优化卷积神经网络结合双向门控循环单元时间序列预测&#xff0c;含优化前后对比预测效果基本介绍模型描述程序设计…

【Linux】死锁、读写锁、自旋锁

文章目录 1. 死锁1.1 概念1.2 死锁形成的四个必要条件1.3 避免死锁 2. 读者写者问题与读写锁2.1 读者写者问题2.2 读写锁的使用2.3 读写策略 3. 自旋锁3.1 概念3.2 原理3.3 自旋锁的使用3.4 优点与缺点 1. 死锁 1.1 概念 死锁是指在⼀组进程中的各个进程均占有不会释放的资源…

Vue3之弹窗

文章目录 第一步、引入JS第二步、弹框 在前端开发语言Vue3&#xff0c;在管理端如何进行弹窗&#xff1f;下面根据API实现效果。 Element API文档&#xff1a; Element-plus文档 搭建环境可参考博客【 初探Vue3环境搭建与nvm使用】 第一步、引入JS <script lang"ts&…

2、Three.js初步认识场景Scene、相机Camera、渲染器Renderer三要素

三要素之间关系&#xff1a; 有了虚拟场景Scene&#xff0c;相机录像Camera&#xff0c;在相机小屏幕上看到的Renderer Scene当前空间 Mesh人在场景 Camera相机录像 Renderer显示器上 首先先描述下Scene&#xff1a; 这个场景为三要素之一&#xff0c;一切需要展示的东西都需…

cin/cout的性能优化和缓冲区同步问题

目录 背景导入 问题 1.1ios::sync_with_stdio(false) 1.2为什么要解除C/C IO流同步? 1.3使用场景 2.1cin和cout的绑定关系 2.2为什么要解除绑定关系? 2.3注意事项 背景导入 大家可以先看一下这段背景知识;后面我会谈谈自己的理解; 1.在C中&#xff0c;标准输⼊输出流…

node.js基础学习-url模块-url地址处理(二)

前言 前面我们创建了一个HTTP服务器&#xff0c;如果只是简单的http://localhost:3000/about这种链接我们是可以处理的&#xff0c;但是实际运用中一般链接都会带参数&#xff0c;这样的话如果我们只是简单的判断链接来分配数据&#xff0c;就会报404找不到链接。为了解决这个问…

基于springboot中小型制造企业质量管理系统源码和论文

信息数据从传统到当代&#xff0c;是一直在变革当中&#xff0c;突如其来的互联网让传统的信息管理看到了革命性的曙光&#xff0c;因为传统信息管理从时效性&#xff0c;还是安全性&#xff0c;还是可操作性等各个方面来讲&#xff0c;遇到了互联网时代才发现能补上自古以来的…

服务器密码错误被锁定怎么解决?

当服务器密码错误多次导致账号被锁定时&#xff0c;解决方法需要根据服务器的操作系统&#xff08;如 Linux 或 Windows &#xff09;和具体服务器环境来处理。以下是常见的解决办法&#xff1a; 一、Linux 服务器被锁定的解决方法 1. 使用其他用户账号登录 如果有其他未被…

Java基础——(四)继承

1. 类、超类和子类 在Java中&#xff0c;通过关键字extends表示继承。extends表明正在构造的新类派生与一个已存在的类&#xff0c;已存在的类称为超类&#xff08;superclass&#xff09;、基类&#xff08;base class&#xff09;或父类&#xff08;parent class&#xff09…

Python语法基础(四)

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 高阶函数之map 高阶函数就是说&#xff0c;A函数作为B函数的参数&#xff0c;B函数就是高阶函数 map&#xff1a;映射 map(func,iterable) 这个是map的基本语法&#xff0c;…

《datawhale2411组队学习 模型压缩技术7:NNI剪枝》

文章目录 一、NNI简介二、 NNI剪枝快速入门2.1 加载并训练模型2.2 模型剪枝2.3 模型加速&#xff08;剪枝永久化&#xff09;2.4 微调压缩模型2.5 Slim Pruner测试 三、 使用NNI3.0进行Bert压缩&#xff08;剪枝、蒸馏)3.1 数据预处理3.2 训练模型3.3 设置模型蒸馏函数3.4 修剪…

day22:lamp项目部署

一&#xff0c;lamp概述 lamp概述 LAMP 是一组开源软件的缩写&#xff0c;用于搭建动态网站或Web应用程序的基础环境。LAMP 代表了四个主要的组成部分&#xff1a; Linux&#xff1a;操作系统&#xff0c;LAMP 环境的基础。通常使用的是 Linux 发行版&#xff0c;如 CentOS、…

【提高篇】3.6 GPIO(六,寄存器介绍,下)

目录 2.3 输出速度寄存器OSPEEDR(GPIOx_OSPEEDR) (x = A..I) 2.4 上拉/下拉寄存器 (GPIOx_PUPDR) (x = A..I) 2.5 输入数据寄存器(IDR) 2.6 输出数据寄存器(ODR) 2.7 置位/复位寄存器(BSRR) 2.8 BSRR与ODR寄存器的区别 2.3 输出速度寄存器OSPEEDR(GPIOx_OSPEEDR) (…

【IMF靶场渗透】

文章目录 一、基础信息 二、信息收集 三、flag1 四、flag2 五、flag3 六、flag4 七、flag5 八、flag6 一、基础信息 Kali IP&#xff1a;192.168.20.146 靶机IP&#xff1a;192.168.20.147 二、信息收集 Nmap -sP 192.168.20.0/24 Arp-scan -l nmap -sS -sV -p- -…

记一次腾讯云海外服务器http能正常访问https访问拒绝问题处理过程

最近双十一, 购了一台腾讯云的海外服务器&#xff0c; 开通后就是一堆的服务器软件安装数据上传和配置&#xff0c;没想到&#xff0c;等待配置完成后才发现https无法正常访问&#xff0c;于是开启了自查。 1. 检查nginx软件的ssl配置 nginx http https配置参考 server {l…

hdlbits系列verilog解答(mt2015_muxdff)-90

文章目录 一、问题描述二、verilog源码三、仿真结果一、问题描述 本节要实现的电路来自于ECE253 2015中期测试问题5。要实现以下如图所示的时序电路中复用器及D触发器子模块。 模块声明 module top_module ( input clk, input L, input r_in, input q_in, output reg Q); 思路…

Android 图形系统之七:SurfaceFlinger

一. 引言 什么是 SurfaceFlinger&#xff1f;SurfaceFlinger 的核心作用和地位&#xff1f;为什么需要了解 SurfaceFlinger&#xff1f; 二. SurfaceFlinger 的基本概念 Surface 和 SurfaceFlinger 的关系SurfaceFlinger 与图形渲染&#xff08;OpenGL ES 和 Vulkan&#xf…