波奇学Linux:进程通信管道

 进程通信

管道:基于文件级别的单向通信

创建父子进程,使得进程的struct file*fd_array[]的文件描述符指向同一个struct file文件,这个文件是内存级文件。

父进程关写端,子进程再关闭读端。实现单向通信

子进程写入,父进程读取。

如果进程不是父子关系,则无法利用管道,因此管道应用于父子或者兄弟进程

以上的管道叫做匿名管道。

创建管道:pipe

输出型参数

pipefd[0]读下标

pipefd[1]写下标

代码示例

#include <iostream>
#include<string>
#include<cstdlib>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>using namespace std;
#define N 2
#define NUM 1024
void Writer(int wfd)
{string s="hello I am child";pid_t self=getpid();int number=0;char buffer[NUM];while(true){buffer[0]=0; //字符串清空//将字符串的内容放入buffer缓冲区中snprintf(buffer,sizeof(buffer),"%s-%d-%d",s.c_str(),self,number++);cout<<buffer<<endl;// 发送给父进程write(wfd,buffer,strlen(buffer));sleep(1);}
}
void Reader(int rfd)
{char buffer[NUM];while(true){buffer[0]=0;// n表示实际读到字节的大小ssize_t n=read(rfd,buffer,sizeof(buffer));if(n>0){buffer[n]=0; //当成字符串加入"\0"cout<<"father get a message["<<getpid()<<"]#"<<buffer<<endl;}}
}
int main()
{int pipefd[]={0};int n=pipe(pipefd);if(n<0) return 1;cout<<"pipefd[0]:"<<pipefd[0]<<", pipefd[1]: "<<pipefd[1]<<endl;pid_t id=fork();if(id<0) return 2;if(id==0) {close(pipefd[0]);//IPC codeWriter(pipefd[1]);close(pipefd[1]);exit(0);}close(pipefd[1]);Reader(pipefd[0]);pid_t rid=waitpid(id,nullptr,0);if(rid<0) return 3;close(pipefd[0]);return 0;
}

然而多执行流会会出现访问冲突的问题--父进程访问的数据到一半时,旧数据被写端覆盖。

父子进程协同,保护管道文件数据安全

读写端正常,如果管道为空,读端阻塞

管道文件有大小,写满写端阻塞

读端正常读,写端关闭,写进程变成僵尸进程,读端就会读到0,表明读到文件结尾,而且不会阻塞

写端正常写,读端关闭,操作系统通过信号杀掉写入的进程。

ulimit查看pipe size大小,但是不同内核可能有差别

管道面向字节流,一次性读完,有多少读多少,且将分割符看成一个普通字符,管道规范可以解决这个问题

管道是基于文件的,文件的生命周期是随进程的

管道的应用场景

使用管道实现简易版本的进程池

 Task.hpp

#pragma once
#include<cstdlib>
#include<iostream>
#include<vector>
#include<unistd.h>
#include<assert.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<string>
typedef void (*task_t)();
std::vector<task_t> tasks;//任务是四个函数
void task1()
{std::cout<<"task 1 call"<<std::endl;
}
void task2()
{std::cout<<"task 2 call"<<std::endl;
}
void task3()
{std::cout<<"task 3 call"<<std::endl;
}
void task4()
{std::cout<<"task 4 call"<<std::endl;
}
// const & 输入 ->向函数内部输入
// * 输出
// & 输入 输出
void LoadTask(std::vector<task_t> *p_tasks)
{p_tasks->push_back(&task1);p_tasks->push_back(&task2);p_tasks->push_back(&task3);p_tasks->push_back(&task4);
}

 ProcessPool.cc

#include "Task.hpp"
//对管道进行描述#define processnum 10
class channel
{
public:channel(int task_id,int pid,std::string processname):_cmdfd(task_id),_pid(pid),_processname(processname){}
public:int _cmdfd;int _pid;std::string _processname;
};
std::vector<channel> channels;
void slaver()
{while(true){int tasknum=0;ssize_t num=read(0,&tasknum,sizeof(int));//read block,等待输入// tasknum=tasknum%tasks.size();// (*tasks[tasknum])();//std::cout<<"i and pid"<<i<<pid<<std::endl;if (!num)break;else{std::cout<<"child process "<<getpid()<<"pid: "<<"receive task_id: "<<tasknum<<std::endl;(*tasks[tasknum])();}}
}
void InitProcessPool(std::vector<channel>* pchannels)
{std::vector<int> oldfds;for (int i=0;i<processnum;i++){//create pipeint pipefd[2];int n=pipe(pipefd);assert(!n); // n=0 successpid_t pid=fork();assert(pid!=-1); //pid =-1 fail//child//std::cout<<"i = "<<i;if(pid==0){   std::cout<<"child process:"<<getpid()<<"have otherfds: ";//only one write fdfor(auto oldfd:oldfds){std::cout<<oldfd<<" ";close(oldfd);}std::cout<<std::endl;//build relationshipclose(pipefd[1]);// pipe read from fd=0 not fd=3;dup2(pipefd[0],0);close(pipefd[0]);// slaver();exit(0);}close(pipefd[0]);int status=0;// ensure one by one ,block until child process finish// pid_t result=waitpid(pid,&status,0);// assert(result!=-1);pchannels->push_back(channel(pipefd[1],pid,"process "+std::to_string(i)));oldfds.push_back(pipefd[1]);sleep(1);}}
void menu()
{std::cout<<"*********************"<<std::endl;std::cout<<"******1.task one*****"<<std::endl;std::cout<<"******2.task two*****"<<std::endl;std::cout<<"******3.task three***"<<std::endl;std::cout<<"******4.task four****"<<std::endl;std::cout<<"******0.quit*********"<<std::endl;std::cout<<"*********************"<<std::endl;
}
void ctrlSlaver()
{int which=0;while(true){menu();int enter=0;std::cout<<"enter number:";std::cin>>enter;std::cout<<std::endl;if (enter==0){std::cout<<"quit software"<<std::endl;//ssize_t n=write(0,&enter,0); 不用写入,直接退出就好了//assert(n!=-1);break;}ssize_t n=write(channels[which]._cmdfd,&enter,sizeof(int));assert(n!=-1);std::cout<<"parent send a task_num "<<enter<<" to process "<<channels[which]._processname<<std::endl;which++;which=which%processnum;}
}
void quitProcess(std::vector<channel>& pchannels)
{for(auto channel:channels){std::cout<<"close process"<<channel._pid<<std::endl;//关闭读端,进程关闭close(channel._cmdfd);wait(NULL);}}
void PrintTask(const std::vector<task_t> tasks)
{for(auto task:tasks){(*task)();}}
int main()
{// load the taskLoadTask(&tasks);//PrintTask(tasks);InitProcessPool(&channels);ctrlSlaver();quitProcess(channels);return 0;
}

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

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

相关文章

C++ Primer 笔记(总结,摘要,概括)——第3章 字符串、向量和数组

目录 3.1 命名空间的using声明 3.2 标准库类型string 3.2.1 定义和初始化string对象 3.2.2 string对象上的操作 3.2.3 处理string对象中的字符 3.3 标准库类型vector 3.3.1 定义和初始化vector对象 3.3.2 向vector对象中添加元素 3.3.3 其他vector操作 3.4 迭代器介绍 3.4.…

如何使用rocketmq实现分布式事务?

什么是rocketmq事务消息 事务消息是 Apache RocketMQ 提供的一种高级消息类型&#xff0c;支持在分布式场景下保障消息生产和本地事务的最终一致性。 RocketMQ的分布式事务又称为“半消息事务”。 事务消息处理流程 RocketMQ是靠半消息机制实现分布式事务 事务消息&#x…

Spring之AOP源码解析(上)

Aop相关注解 EnableTransactionManagementEnableAspectJAutoProxyEnableAsync... 从注解切入来看看这些注解都干了什么 Import注解作用简述 注入的类一般继承ImportSelector或者ImportBeanDefinitionRegistrar接口 继承ImportSelector接口&#xff1a;selectImports方法返回…

pandas/geopandas 笔记:判断地点在不在路网上 不在路网的点和路网的距离

0 导入库 import osimport pandas as pd pd.set_option(display.max_rows,5)import osmnx as oximport geopandas as gpd from shapely.geometry import Point 1 读取数据 假设我们有 如下的数据&#xff1a; 1.1 新加坡室外基站位置数据 cell_stationpd.read_csv(outdoor…

TSINGSEE青犀AI智能分析网关V4初始配置与算法相关配置介绍

TSINGSEE青犀AI智能分析网关V4内置了近40种AI算法模型&#xff0c;支持对接入的视频图像进行人、车、物、行为等实时检测分析&#xff0c;上报识别结果&#xff0c;并能进行语音告警播放。硬件管理平台支持RTSP、GB28181协议、以及厂家私有协议接入&#xff0c;可兼容市面上常见…

linux下ffmpeg调用GPU硬件解码(VDPAU/VAAPI)保存文件

本文讲解在linux下面&#xff0c;如何通过ffmpeg调用GPU硬件解码&#xff0c;并保存解码完的yuv文件。 其实&#xff0c;ffmpeg自带的例子hw_decode.c这个文件&#xff0c;就已经能满足要求了&#xff0c;因此&#xff0c;本文就尝试讲解以下hw_decode这个例子。hw_decode.c可以…

watchpoint

前言 内存被踩&#xff0c;通过 watchpoint 找到真凶 实例 以 smsc911x 网卡驱动为基体&#xff0c;进行实验&#xff0c;和网卡本身功能无关&#xff0c; 每执行一次 ifconfig eth0 up&#xff0c;就会调用一次 smsc911x_open()&#xff0c;我在这里设计了一段代码&#xf…

数学知识(四)(容斥原理、博弈论)

一、容斥原理 容斥原理公式 一共加或者减的式子个数 &#xff08;一&#xff09;利用容斥原理解决求能被质数整除的数的个数 890计算能被整除的数的个数 因为一共有2^n-1种选法&#xff0c;可以用位运算的方式枚举&#xff0c;对于得到的每一种选法&#xff0c;根据存在的数…

六、回归与聚类算法 - 逻辑回归与二分类

线性回归欠拟合与过拟合线性回归的改进 - 岭回归分类算法&#xff1a;逻辑回归模型保存与加载无监督学习&#xff1a;K-means算法 1、应用场景 2、原理 2.1 输入 2.2 激活函数 3、损失以及优化 3.1 损失 3.2 优化 4、逻辑回归API 5、分类的评估方法 5.1 精确率和召回率 5.2…

【Spring】IoC容器 控制反转 与 DI依赖注入 配置类实现版本 第四期

文章目录 基于 配置类 方式管理 Bean一、 配置类和扫描注解二、Bean定义组件三、高级特性&#xff1a;Bean注解细节四、高级特性&#xff1a;Import扩展五、基于注解配置类方式整合三层架构组件总结 基于 配置类 方式管理 Bean Spring 完全注解配置&#xff08;Fully Annotatio…

Kotlin学习 6

1.接口 interface Movable {var maxSpeed: Intvar wheels: Intfun move(movable: Movable): String}class Car(var name: String, override var wheels: Int 4, _maxSpeed: Int) : Movable {override var maxSpeed: Int _maxSpeedget() fieldset(value) {field value}overr…

C语言读取 ini 配置文件,修改/添加键值对

C语言读取 ini 配置文件&#xff0c;修改/添加键值对 C语言读取 ini 配置文件&#xff0c;对section中的键值对进行修改/添加&#xff0c;如果section不存在&#xff0c;则在末尾将新的section/key/value 添加进去。 一、了解什么是INI文件&#xff1f; ini 文件是Initializ…

【大数据】Flink 之部署篇

Flink 之部署篇 1.概述和参考架构2.可重复的资源清理3.部署模式3.1 Application 模式3.2 Per-Job 模式&#xff08;已废弃&#xff09;3.3 Session 模式 Flink 是一个多用途框架&#xff0c;支持多种不同的混合部署方案。下面&#xff0c;我们将简要介绍 Flink 集群的构建模块、…

【html学习笔记】3.表单元素

1.文本框 1.1 语法 <input type "text">表示文本框。且只能写一行 1.2 属性 使用属性size 设置文本框大小 <input type"text" size"10">2. 使用属性value 来设置文本框的默认文字 <input type"text" size"…

Vue状态管理库-Pinia

一、Pinia是什么&#xff1f; Pinia 是 Vue 的专属状态管理库&#xff0c;它允许支持跨组件或页面共享状态&#xff0c;即共享数据&#xff0c;他的初始设计目的是设计一个支持组合式API的 Vue 状态管理库&#xff08;因为vue3一个很大的改变就是组合式API&#xff09;,当然这…

PFA三角烧瓶实验室PFA锥形瓶本底纯净耐腐蚀性强

PFA三角烧瓶外观呈平底圆锥状&#xff0c;下阔上狭&#xff0c;有一圆柱形颈部&#xff0c;上方有一较颈部阔的开口&#xff0c;可用塞子封闭。PFA三角烧瓶也称PFA锥形瓶&#xff0c;PFA反应瓶&#xff0c;PFA三角烧瓶、PFA依氏烧瓶、PFA锥形烧瓶&#xff0c;PFA鄂伦麦尔瓶等。…

普中51单片机学习(串口通信)

串口通信 原理 计算机通信是将计算机技术和通信技术的相结合&#xff0c;完成计算机与外部设备或计算机与计算机之间的信息交换 。可以分为两大类&#xff1a;并行通信与串行通信。并行通信通常是将数据字节的各位用多条数据线同时进行传送 。控制简单、传输速度快&#xff1…

【Python】Python实现串口通信(Python+Stm32)

&#x1f389;欢迎来到Python专栏~Python实现串口通信 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;Python学习专栏 文章作者技术和水平有限&#xff0c;如果文中出现错误&#xff0c;希望…

springboot208基于springboot物流管理系统

基于spring boot物流管理系统设计与实现 摘 要 社会发展日新月异&#xff0c;用计算机应用实现数据管理功能已经算是很完善的了&#xff0c;但是随着移动互联网的到来&#xff0c;处理信息不再受制于地理位置的限制&#xff0c;处理信息及时高效&#xff0c;备受人们的喜爱。…

maven工程打包引入本地jar包

1、通过maven生成本地区仓库包 mvn install:install-file --settings D:\lkx\download\apache-maven-3.6.3\conf\settings.xml -Dfileaspose-cad-21.8.jar -DartifactIdaspose-cad -DgroupIdsystem.core -Dversion21.8 -Dpackagingjar -DgeneratePomtrue # --settings&#xf…