【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
相关文章:

【Linux进程间通信】用管道实现简单的进程池、命名管道
【Linux进程间通信】用管道实现简单的进程池、命名管道 目录 【Linux进程间通信】用管道实现简单的进程池、命名管道为什么要实现进程池?代码实现命名管道创建一个命名管道 理解命名管道匿名管道与命名管道的区别命名管道的打开规则 作者:爱写代码的刚子…...

Linux操作系统基础(九):Linux用户与权限
文章目录 Linux用户与权限 一、文件权限概述 二、终端命令:组管理 三、终端命令:用户管理 1、创建用户 、 设置密码 、删除用户 2、查看用户信息 3、su切换用户 4、sudo 4.1、给指定用户授予权限 4.2、使用 用户 zhangsan登录, 操作管理员命令…...

蓝桥杯——第 5 场 小白入门赛(c++详解!!!)
文章目录 1 十二生肖基本思路: 2 欢迎参加福建省大学生程序设计竞赛基本思路:代码: 3 匹配二元组的数量基本思路:代码: 4 元素交换基本思路:代码: 5 下棋的贝贝基本思路:代码: 6 方程…...

Codeforces Round 303 (Div. 2)C. Kefa and Park(DFS、实现)
文章目录 题面链接题意题解代码总结 题面 链接 C. Kefa and Park 题意 求叶节点数量,叶节点满足,从根节点到叶节点的路径上最长连续1的长度小于m 题解 这道题目主要是实现,当不满足条件时直接返回。 到达叶节点后统计答案,用…...
797. 差分
Problem: 797. 差分 文章目录 思路解题方法复杂度Code 思路 这是一个差分数组的问题。差分数组的主要适用场景是频繁对原始数组的某一个区间进行增减操作。这种操作是区间修改操作,在这种操作下,差分数组只需要对区间的两个端点进行操作,时间…...

2024.2.5 vscode连不上虚拟机,始终waiting for server log
昨天还好好的,吃着火锅,做着毕设,突然就被vscode给劫了。 起初,哥们跟着网上教程有模有样地删除了安装包缓存,还删除了.vscode-server,发现没卵用,之前都是搜那个弹窗报错。 后来发现原来是vsco…...

CSS基础---新手入门级详解
CSS:层叠样式表 CSS(Cascading Style Sheets,层叠样式表),是一种用来为结构化文档添加样式(字体、间距和颜色)的计算机语言,css扩展名为.css。 实例: <!DOCTYPE html><html> <head><…...
Python中Pymysql库的常见用法和代码示例
关注B站可以观看更多实战教学视频:肆十二-的个人空间-肆十二-个人主页-哔哩哔哩视频 (bilibili.com) pymysql是一个用于连接MySQL数据库的Python库,它允许你执行SQL查询并处理返回的结果。以下是pymysql库的一些常见用法和代码示例: 1. 安装…...

使用 WPF + Chrome 内核实现高稳定性的在线客服系统复合应用程序
对于在线客服与营销系统,客服端指的是后台提供服务的客服或营销人员,他们使用客服程序在后台观察网站的被访情况,开展营销活动或提供客户服务。在本篇文章中,我将详细介绍如何通过 WPF Chrome 内核的方式实现复合客服端应用程序。…...
fastapi mysql 开发restful 3
pip install mysql-connector-python pymysql 数据库链接 创建src目录,里面创建db.py 代码如下: # 导入mysql.connector模块,该模块提供了与MySQL数据库进行连接和交互的功能。 import mysql.connector # 定义一个函数get_db_connectio…...
【Uniapp uni-app学习与快速上手——详细讲解】
Uniapp uni-app学习与快速上手——详细讲解 1. 介绍2. Uni-app 学习资源3. 快速上手4. 开始第一个项目5. 调试和发布 1. 介绍 Uni-app 是一个使用 Vue.js 编写多端应用的前端框架。开发者可以编写一份代码,然后发布到iOS、Android、网页(响应式…...

剑指offer——旋转数组的最小数字
目录 1. 题目描述2. 分析思路2.1 示例分析 3. 更完美的做法 1. 题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3.4,5,1.2}为{1.2,3,4,5}的一个旋转&a…...

盘点数据可视化大屏焦点图十种样式
所谓焦点图就是大屏中居于中心位置的图,是视觉的中心,本位列举了十种焦点图样式供大家参考。 地球作为焦点图 图片来自网络 地图作为焦点图 图片来自网络 城市作为焦点图 图片来自网络 园区做焦点图 图片来自网络 建筑做焦点图 图片来自网络 生产线…...
问题 G: 老鼠和猫的交易
题目描述 小老鼠准备了M磅的猫粮,准备去和看守仓库的猫做交易,因为仓库里有小老鼠喜欢吃的五香豆。 仓库有N个房间; 第i个房间有J[i] 磅的五香豆,并且需要用F[i]磅的猫粮去交换; 老鼠不必交换该房间所有的五香豆&…...

HiveSQL——借助聚合函数与case when行转列
一、条件函数 if 条件函数 if函数是最常用到的条件函数,其写法是if(xn,a,b), xn代表判断条件,如果xn时,那么结果返回a ,否则返回b。 selectif(age < 25 or age is null, 25岁以下, 25岁以上) as age_cnt,count(1) as number from table…...
冒泡排序,判断回文,以及12-24小时制
6-7 定义函数,完成冒泡排序算法。 本题定义一个冒泡排序算法的函数,调用函数后实现数组的升序排序,其数组长度为任意长度。 函数接口定义: 在这里描述函数接口。例如: void sort(int arr[],int n); 在这里解释接口…...

【Vue】computed与watch
📝个人主页:五敷有你 🔥系列专栏:Vue⛺️稳重求进,晒太阳 计算属性 概念:基于现有的数据,计算出来新的属性,依赖的数据变化,自动重新计算 语法: 声明…...

探索设计模式的魅力:捕捉变化的风-用观察者模式提升用户体验
设计模式专栏:http://t.csdnimg.cn/U54zu 目录 一、引言 核心概念 应用场景 可以解决的问题 二、场景案例 2.1 不用设计模式实现 2.2 存在问题 2.3 使用设计模式实现 2.4 成功克服 三、工作原理 3.1 结构图和说明 3.2 工作原理详解 3.3 实现步骤 四、 优…...

SpringCloud-高级篇(十九)
我们已经学过使用 SpringAMQP去收和发消息,但是发和收消息是只是MQ最基本的功能了,在收发消息的过程中,会有很多的问题需要去解决,下面需要学习rabbitMQ的高级特性去解决 死信交换机:这个可以帮助我们实现消息的延迟的…...
Junit常用断言
0.断言简介 断言:assert Q:断言的作用 更方便的对结果进行判定 "有针对性"的if判断 针对两个变量值是否相同 使用assertEquals针对两个对象是否相同 使用assertSame针对返回值是否为True 使用assertTrue 1.断言的参数 assertXXX(”断言失败时提升的信息“&#x…...
解决MySQL8.4报错ERROR 1524 (HY000): Plugin ‘mysql_native_password‘ is not loaded
最近使用了MySQL8.4 , 服务启动成功,但是就是无法登陆,并且报错: ERROR 1524 (HY000): Plugin mysql_native_password is not loaded 使用如下的命令也报错 mysql -u root -p -P 3306 问题分析: 在MySQL 8.0版本中,默认的认证插件从mysql_native_password变更为cachi…...

4G无线网络转串口模块 DTU-1101
4G无线网络转串口模块概述 4G无线网络转串口模块是一种工业通信设备,通过4G网络将串口(如RS232/RS485)设备接入互联网,实现远程数据传输与控制。适用于物联网(IoT)、工业自动化、远程监控等场景。 核心功能…...
抖音怎么下载没有水印的视频?
你是不是经常在抖音上刷到喜欢的视频,想保存下来却总是带着烦人的水印?无论是想收藏精彩片段,还是二次创作,水印都成了“拦路虎”。别急!今天就来教你3种超简单方法,轻松下载无水印抖音视频,高清…...

PDF图片和表格等信息提取开源项目
文章目录 综合性工具专门的表格提取工具经典工具 综合性工具 PDF-Extract-Kit - opendatalab开发的综合工具包,包含布局检测、公式检测、公式识别和OCR功能 仓库:opendatalab/PDF-Extract-Kit特点:功能全面,包含表格内容提取的S…...
用 NGINX 构建高效 SMTP 代理`ngx_mail_smtp_module`
一、模块定位与作用 协议代理 NGINX 监听指定端口(如 25、587、465 等),接收客户端的 SMTP 会话请求。代理层在会话中透明转发客户端的 EHLO、MAIL FROM、RCPT TO、DATA 等命令到后端 MTA。 认证控制 通过 smtp_auth 指令指定允许的 SASL 认…...
MySQL连接报SSL错误
问题(cmd) C:\Users>mysql -h xx.xx.xx.xx -u root -p Enter password: ERROR 2026 (HY000): SSL connection error: error:0A000102:SSL routines::unsupported protocol 解决方案 1. 临时禁用 SSL 连接(不推荐生产环境使用࿰…...

第4天:RNN应用(心脏病预测)
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 目标 具体实现 (一)环境 语言环境:Python 3.10 编 译 器: PyCharm 框 架: Pytorch (二)具体步骤…...
元器件基础学习笔记——结型场效应晶体管 (JFET)
场效应晶体管(Field Effect Transistor,FET)简称场效应管,是一种三端子半导体器件,它根据施加到其其中一个端子的电场来控制电流的流动。与双极结型晶体管 (BJT) 不同,场效应晶体管 …...
camera功能真的那么难用吗
背景 Android开发工作过程中,经常需要用到camera相关能力,比如:人脸识别,ai识别,拍照预览,摄像头录制等等需求。都需要使用到camera,且需要拿到camera的预览数据。但是每次开发这块代码都比较繁…...
JavaScript 本地存储 (localStorage) 完全指南
文章目录 JavaScript 本地存储 (localStorage) 完全指南 🔐一、什么是 localStorage?💡二、如何使用 localStorage?🔧1. 存储数据2. 读取数据3. 删除数据4. 清空所有数据 三、存储对象和数组的技巧 🎨1. 存…...