【Linux进程间通信】用管道实现简单的进程池、命名管道

【Linux进程间通信】用管道实现简单的进程池、命名管道

目录

  • 【Linux进程间通信】用管道实现简单的进程池、命名管道
    • 为什么要实现进程池?
    • 代码实现
      • 命名管道
        • 创建一个命名管道
      • 理解命名管道
        • 匿名管道与命名管道的区别
        • 命名管道的打开规则

作者:爱写代码的刚子

时间:2024.2.10

前言:本篇博客将会介绍并实现简单的线程池

为什么要实现进程池?

  • 系统调用是有成本的,池化技术是为了我们的访问速度和效率
  • 在需要频繁的创建删除较多进程的情况下,导致计算机资源消耗过多
  • 进程池则是创建指定进程数量等待执行事件,避免了不必要的创建和销毁过程

代码实现

  • ProcessPool_Task.hpp
#pragma once#include <iostream>
#include <functional>
#include <vector>using task_t=std::function<void()>;
//typedef void(*task_t)();
void task1()
{std::cout<<"task1"<<std::endl;
}void task2()
{std::cout<<"task2"<<std::endl;
}void task3()
{std::cout<<"task3"<<std::endl;
}void task4()
{std::cout<<"task4"<<std::endl;
}void LoadTask(std::vector<task_t> *tasks)
{tasks->push_back(task1);tasks->push_back(task2);tasks->push_back(task3);tasks->push_back(task4);}
  • ProcessPool.cc
#include "ProcessPool_Task.hpp"
#include <string>
#include <vector>
#include <ctime>
#include <unistd.h>
#include <cstdlib>
#include <cassert>
#include <iostream>#include <sys/wait.h>
#include <sys/stat.h>const int processnum = 5;
//描述std::vector<task_t> tasks;
class channel
{ 
public:channel(int cmdfd,int slaverid,const std::string &processname):_cmdfd(cmdfd),_slaverid(slaverid),_processname(processname){}public:int _cmdfd;pid_t _slaverid;std::string _processname;
};void slaver()
{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;}
}
//参数规范
//输入:const &
//输出:*
//输入输出:&void InitProcessPool(std::vector<channel> *channels)
{//确保每一个子进程都只有一个写端std::vector<int> oldfds;for(int i=0;i<processnum;++i){int pipefd[2];//临时空间int n = pipe(pipefd);assert(!n);(void)n;pid_t id = fork();if(id==0)//子进程,子进程拿到的pipefd都是3{std::cout<< "child" << getpid() << "close history fd: ";for(auto fd : oldfds) {std::cout<<fd<<" ";close(fd);}std::cout<<"\n";close(pipefd[1]);dup2(pipefd[0],0);//将pipefd[0]重定向到0,将来直接往键盘文件(fd为0)文件里面读即可。close(pipefd[0]);slaver();std::cout<< "process : "<< getpid() << "quit" <<std::endl;//方法一://slaver(pipefd[0]);exit(0);}//父进程,父进程拿到的pipefd是4,5,6...close(pipefd[0]);//添加channel字段std::string name = "process-"+ std::to_string(i);channels->push_back(channel(pipefd[1],id,name ));//pipefd[1]表示父进程要往pipefd[1]里面写oldfds.push_back(pipefd[1]);}
}void Debug(const std::vector<channel> &channels)
{for(const auto &c : channels){std::cout<<c._cmdfd<<" "<<c._slaverid<<" "<<c._processname << std::endl;}
}void ctrlSlaver(const std::vector<channel> &channels)
{int which = 0;//轮转的方式while(true){//1.选择任务int cmdcode = rand()%tasks.size();//2.选择进程//[负载均衡(1.随机数 2.轮转)]int processpos = rand()%channels.size();//3.发送任务write(channels[which]._cmdfd,&cmdcode,sizeof(cmdcode));++which;which %= channels.size();sleep(1);}
}void QuitProcess(const std::vector<channel> &channels)
{//for(const auto &c : channels) close(c._cmdfd);//for(const auto &c : channels) waitpid(c._slaverid,nullptr,0);//这里存在子进程有多个写端的问题,解决办法://方法一.从后往前关闭子进程int last = channels.size()-1;for(int i= last;i>= 0;i--){close(channels[i]._cmdfd);waitpid(channels[i]._slaverid,nullptr,0);}//方法二.确保每一个子进程都只有一个写端}
int main()
{LoadTask(&tasks);//随机数srand(time(nullptr)^getpid()^1023);//组织std::vector<channel> channels;//将特定的结构转化为数据的增删查改//初始化InitProcessPool(&channels);Debug(channels);//控制子进程ctrlSlaver(channels);//清理收尾QuitProcess(channels);return 0;
}

图解:

在这里插入图片描述

命名管道

  • 管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。

  • 如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。

  • 命名管道是一种特殊类型的文件

创建一个命名管道
  • $ mkfifo filename在命令行上创建命名管道

在这里插入图片描述

p开头表示这是命名管道(但是并不在磁盘上),同时管道文件的大小为0

在这里插入图片描述

  • *int mkfifo(const char filename, mode_t mode); 程序中创建命名管道的函数

理解命名管道

不同的两个进程打开同一个文件的时候,在内核中操作系统文件描述符只会指向同一个文件,进程间通信的前提:先让不同的进程看到同一份资源,管道文件则不需要进行刷盘(内存级文件),所以大小为0字节。

【问题】:如何保证打开的是同一个文件?看到同一个路径下的同一个文件名。(inode),即= 路径 + 文件名(唯一性)

匿名管道与命名管道的区别

匿名管道由pipe函数创建并打开。

命名管道由mkfifo函数创建,打开用open

FIFO(命名管道)与pipe(匿名管道)之间唯一的区别在它们创建与打开的方式不同,一但这些工作完成之后,它们具有相同的语义。

命名管道的打开规则
  • 如果当前打开操作是为读而打开FIFO时

    • O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO
    • O_NONBLOCK enable:立刻返回成功
  • 如果当前打开操作是为写而打开FIFO时

    • O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO
    • O_NONBLOCK enable:立刻返回失败,错误码为ENXIO

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

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

相关文章

RabbitMQ之五种消息模型

1、 环境准备 创建Virtual Hosts 虚拟主机&#xff1a;类似于mysql中的database。他们都是以“/”开头 设置权限 2. 五种消息模型 RabbitMQ提供了6种消息模型&#xff0c;但是第6种其实是RPC&#xff0c;并不是MQ&#xff0c;因此不予学习。那么也就剩下5种。 但是其实3、4…

基于centos的Linux中如何安装python

前言 之前在linux上安装python的时候没来及记录下来&#xff0c;感觉还是有必要的&#xff0c;所以现在打算把原来装好的python卸载掉&#xff0c;然后重装一遍&#xff0c;重新记录一下。当前环境是否安装python 通过查询我发现机器里有3个版本的python&#xff0c;第一个是…

《统计学简易速速上手小册》第7章:时间序列分析(2024 最新版)

文章目录 7.1 时间序列数据的特点7.1.1 基础知识7.1.2 主要案例&#xff1a;股票市场分析7.1.3 拓展案例 1&#xff1a;电商销售预测7.1.4 拓展案例 2&#xff1a;能源消耗趋势分析 7.2 时间序列模型7.2.1 基础知识7.2.2 主要案例&#xff1a;股价预测7.2.3 拓展案例 1&#xf…

Oracle的学习心得和知识总结(三十二)|Oracle数据库数据库回放功能之论文四翻译及学习

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《Oracle Database SQL Language Reference》 2、参考书籍&#xff1a;《PostgreSQL中文手册》 3、EDB Postgres Advanced Server User Gui…

5G NR 频率计算

5G中引入了频率栅格的概念&#xff0c;也就是小区中心频点和SSB的频域位置不能随意配置&#xff0c;必须满足一定规律&#xff0c;主要目的是为了UE能快速的搜索小区&#xff1b;其中三个最重要的概念是Channel raster 、synchronization raster和pointA。 1、Channel raster …

多模态知识图谱:感知与认知的交汇

目录 前言1 多模态知识图谱的概念1.1 感知系统与认知系统的连接1.2 信息形式的整合与融合1.3 全面、多维度的认知基础 2 多模态的作用2.1 模态的知识互补2.2 模态实体消歧2.3 模态语义搜索2.4 知识图谱补全2.5 多模态任务增强 3 多模态知识图谱发展历史3.1 初期模态数据整合3.2…

基于POSCMS架构开发的素材资源网平台整站全面修复版源码

(购买本专栏可免费下载栏目内所有资源不受限制,持续发布中,需要注意的是,本专栏为批量下载专用,并无法保证某款源码或者插件绝对可用,介意不要购买) 资源简介 基于POSCMS架构开发的素材资源网平台整站全面修复版源码一键安装版 系统功能介绍 支持文章、论坛、下载、…

vulnhub-->hacksudo-Thor靶机详细思路

目录 1. IP探测2.端口服务扫描3.网站漏洞扫描4.目录扫描5.信息分析6.破壳漏洞(Shellshock)nmap---漏洞检测CVE-2014-6271 7.nc反弹8.提权9.service提权 1. IP探测 ┌──(root㉿kali)-[~] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:10:3c:9b, IPv4: 19…

国产航顺HK32F030M: 超声波测距模块串口通信数据接收与处理

参考代码 /************************************************************************************************** * file usart_async_tx_no_int_rx_rxneint.c * brief 异步串口通信例程, 通过查询TXE标志发送数据,通过RXNE中断接收数据,当中断接收到数据后会将 * …

2月11日作业

1、请使用递归实现n! 代码&#xff1a; #include<stdio.h> #include<string.h> #include<stdlib.h>int fun(int n) {if(n1)return 1;else{return n*fun(n-1);} }int main(int argc, const char *argv[]) {int n;printf("please enter n:");scanf…

【浙大版《C语言程序设计实验与习题指导(第4版)》】实验7-1-6 求一批整数中出现最多的个位数字(附测试点)

定一批整数&#xff0c;分析每个整数的每一位数字&#xff0c;求出现次数最多的个位数字。例如给定3个整数1234、2345、3456&#xff0c;其中出现最多次数的数字是3和4&#xff0c;均出现了3次。 输入格式&#xff1a; 输入在第1行中给出正整数N&#xff08;≤1000&#xff0…

cesium系列篇:Entity vs Primitive 源码解析(从Entity到Primitive)02

上篇文章中&#xff0c;我们介绍了使用viewer.entities.add添加entity之后的信号传递以及最后entity对象被传递到GeometryVisualizer&#xff1b; 这篇文章&#xff0c;我们则介绍如何在逐帧渲染的过程中根据GeometryVisualizer中的entity对象创建相应的primitive 这是下文中…

vue3 之 组合式API—模版引用

模版引用的概念 通过ref标识获取真实的dom对象或者组件实例对象 如何使用&#xff08;以获取dom为例 组件同理&#xff09; 1️⃣调用ref函数生成一个ref对象 2️⃣通过ref标识绑定ref对象到标签 dom中使用 父组件中可以看到打印出来proxy里面只有一个属性&#xff0c;其他…

【Linux】学习-文件的软硬链接

文件的软硬链接 在上一篇拓展篇—文件系统中我们介绍过文件元的概念&#xff1a; 我们在使用ls -l命令查看文件元信息的时候&#xff0c;有一个硬链接数&#xff0c;说明文件的硬链接数属于文件的属性之一&#xff0c;那么硬链接究竟是什么呢&#xff1f;软链接又是什么呢&…

Spring AI - 使用向量数据库实现检索式AI对话

Spring AI - 使用向量数据库实现检索式AI对话 Spring AI 并不仅限于针对大语言模型对话API进行了统一封装&#xff0c;它还可以通过简单的方式实现LangChain的一些功能。本篇将带领读者实现一个简单的检索式AI对话接口。 一、需求背景 在一些场景下&#xff0c;我们想让AI根据…

华为机考入门python3--(10)牛客10-字符个数统计

分类&#xff1a;字符 知识点&#xff1a; 字符的ASCII码 ord(char) 题目来自【牛客】 def count_unique_chars(s): # 创建一个空集合来保存不同的字符 unique_chars set() # 遍历字符串中的每个字符 for char in s: # 将字符转换为 ASCII 码并检查是否在范围内 #…

KEIL-MDK的时间戳之time.h 结合gd32f1的RTC应用

KEIL-MDK的时间戳之time.h 的应用 1 时间戳介绍 现在物联网产品的在进行通讯的时候&#xff0c;需要加入时间戳的这个信息参数&#xff0c;方便服务器和产品之间交换时间信息。 时间戳是计算机系统中用来表示日期和时间的一种方式&#xff0c;通常是一个数字或者一串字符&am…

[优雅的面试] 进程 线程 协程分的清

面试官大佬&#xff1a;小伙子&#xff0c;咱今儿个先聊聊进程线程这块的知识哈&#xff0c;就先说说进程吧。 我&#xff1a;存储在硬盘中的代码是静态文件&#xff0c;运行中的程序被称为进程。进程之间数据是相互隔离的。 一般说来&#xff0c;一个进程并不是自始至终连续不…

Vits2.3-Extra-v2:中文特化,如何训练及推理(新手教程)

环境&#xff1a; Vits2.3-Extra-v2:中文特化修复版 auto_DataLabeling 干声10分钟左右.wav 问题描述&#xff1a; Vits2.3-Extra-v2:中文特化&#xff0c;如何训练及推理&#xff08;新手教程&#xff09; 解决方案&#xff1a; 一、准备数据集 切分音频 本次音频数据…

管理就是闭环

管理是什么&#xff1f;这个问题没有一个统一的答案。本文提供一个管中窥豹的答案&#xff1a;管理就是闭环。 作为基层管理者&#xff0c;日常管理事务&#xff0c;一个是目标闭环&#xff0c;一个是执行闭环。这分别对应敏捷PO和Scrum Master的职责。PO的职责是确保目标闭环&…