【Linux】进程池
目录
进程池
进程池的概念:
手搓进程池:
1、创建信道和子进程
2、通过channel控制子进程
3、回收管道和子进程
进程池
进程池的概念:
定义一个池子,在里面放上固定数量的进程,有需求来了,就拿一个池中的进程来处理任务,等到处理完毕,进程并不关闭,直接将进程再放回进程池中继续等待任务;
如果有很多任务需要执行,池中的进程数量不够,任务就要等待之前的进程执行任务完毕归来,拿到空闲进程才能继续执行。也就是说,进池中进程的数量是固定的,那么同一时间最多有固定数量的进程在运行;这样不会增加操作系统的调度难度,还节省了开关进程的时间,也一定程度上能够实现并发效果。
看下图,父进程和子进程之间可以通过管道来交互;
如果管道中没有数据,则worker进程就阻塞等待;master向哪个管道写入就唤醒哪一个子进程来处理任务;

手搓进程池:
1、创建信道和子进程
我们用一个类来录父进程读写端的fd和子进程的id,用vector来存储;
- 先来创建一个管道(pipe)
- 管道创建成功后,再创建子进程(fork)
- 关闭不需要的fd
- 将信息存储到vector中
可以将上述代码封装到一个函数中,这样比较好看
#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
using namespace std;class channel
{
public:channel(int wfd, pid_t id, const string &name) : _wfd(wfd), childid(id), _name(name){}~channel(){}int getwfd() { return _wfd; }pid_t getid() { return childid; }string getname() { return _name; }private:int _wfd;pid_t childid;string _name;
};void work(int rfd)
{
}void create(vector<channel> &channels, int num)
{for (int i = 0; i < num; i++){int pipfd[2] = {0};int n = pipe(pipfd);pid_t id = fork();if (id == 0){// child --readclose(pipfd[1]);work(pipfd[0]);close(pipfd[0]);exit(0);}// father --writeclose(pipfd[0]);string name = "channel-" + to_string(i);channels.push_back(channel(pipfd[1], id, name));close(pipfd[1]);}}int main(int argc, char *argv[])
{if (argc != 2){cerr << "processnum???" << endl;return 1;}int num = stoi(argv[1]);// 1、创建子进程和信道vector<channel> channels;create(channels, num);for (auto channel : channels){cout << channel.getid() << " " << channel.getwfd() << " " << channel.getname() << endl;}}
运行结果:

2、通过channel控制子进程
信道建立好后,下面就是接收主进程给我们的任务就可以了,可是子进程如何接收和识别任务呢?
这里我们可以开一个hpp文件来模拟我们的任务:
.hpp文件是允许声明和实现写到一起的;
在这个文件中使用函数指针类型来初始化,并且有随机选择任务的函数,执行任务的函数;
#pragma once#include <iostream>
#include <ctime>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
using namespace std;#define NUM 3
typedef void (*task_t)();task_t tasks[NUM];// 创建任务
void Print()
{cout << "I am Print Task" << endl;
}
void Flush()
{cout << "I am Flush Task" << endl;
}
void Download()
{cout << "I am Download Task" << endl;
}// 初始化
void Loadtask()
{srand(time(nullptr) ^ getpid());tasks[0] = Print;tasks[1] = Download;tasks[2] = Flush;
}void Excutetask(int num)
{if (num < 0 || num > 2)return;tasks[num]();
}int selecttask()
{return rand()%NUM;
}
完成.hpp文件后,在我们的.cpp文件中添加对应的头文件;
- 随机选择一个任务
- 选择信道和进程
- 发送任务----父进程完成write操作,子进程完成read操作


运行结果:

3、回收管道和子进程
- 关闭所有w端
- wait,回收子进程

完整代码:
#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include "test.hpp"
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;class channel
{
public:channel(int wfd, pid_t id,const string &name) : _wfd(wfd), childid(id), _name(name){}~channel(){}int getwfd() { return _wfd; }pid_t getid() { return childid; }string getname() { return _name; }void closechannel(){close(_wfd);}void wait(){pid_t rid =waitpid(childid,nullptr,0);if(rid>0){cout<<"wair sucess"<<endl;}}private:int _wfd;pid_t childid;string _name;
};void work(int rfd)
{while (true){int command = 0;int n = read(rfd, &command, sizeof(command));if (n == sizeof(int)){Excutetask(command);}}
}void create(vector<channel> &channels, int num)
{for (int i = 0; i < num; i++){int pipfd[2] = {0};int n = pipe(pipfd);pid_t id = fork();if (id == 0){// child --readclose(pipfd[1]);work(pipfd[0]);close(pipfd[0]);exit(0);}// father --writeclose(pipfd[0]);string name = "channel-";name += to_string(i);channels.push_back(channel(pipfd[1], id, name));}
}int selectchannel(int num)
{static int index = 0;int next = index;index++;index %=num;return next;
}
void send(int selectnum, int channel_index, vector<channel> &channels)
{write(channels[channel_index].getwfd(), &selectnum, sizeof(selectnum));
}void controlonce(vector<channel> &channels)
{// 2.1、选一个任务int selectnum = selecttask();// 2.2、选一个信道和进程int channel_index = selectchannel(channels.size());// 2.3、发送---父进程w,子进程rsend(selectnum, channel_index, channels);cout << "信息发送成功" << endl;
}
void control(vector<channel> &channels, int times = -1)
{if (times > 0){while(times--){controlonce(channels);}}else{while (true){controlonce(channels);}}
}void clean(vector<channel> &channels)
{for(auto channel:channels){channel.closechannel();}for(auto channel:channels){channel.wait();}
}int main(int argc, char *argv[])
{if (argc != 2){cerr << "processnum???" << endl;return 1;}int num = stoi(argv[1]);Loadtask();// 1、创建子进程和信道vector<channel> channels;create(channels, num);// for (auto channel : channels)// {// cout << channel.getid() << " " << channel.getwfd() << " " << channel.getname() << endl;// }// 2、通过channel控制子进程control(channels, 10);//3、回收管道和子进程clean(channels);
}
以上就是进程池的知识点,希望有所帮助!!!
相关文章:
【Linux】进程池
目录 进程池 进程池的概念: 手搓进程池: 1、创建信道和子进程 2、通过channel控制子进程 3、回收管道和子进程 进程池 进程池的概念: 定义一个池子,在里面放上固定数量的进程,有需求来了,就拿一个池中…...
实验23:DA呼吸灯实验
电路硬件: 实现功能: 代码: public.h #ifndef _public_H #define _public_H#include "reg52.h" //#include "key.h"typedef unsigned int u16; typedef unsigned char u8;void delay_10us(u16 n); void delay_ms(u16 ms);#endif public.c #include …...
安科瑞智慧能源管理系统EMS3.0在浙江某能源集团有限公司的应用
安科瑞戴婷 Acrel-Fanny 一、项目背景 浙江某能源集团有限公司位于浙江省宁波前湾新区,主营业务范围包括了储能技术服务,光伏风力发电技术服务,充电桩技术服务,新能源项目的施工以及为企业提供配电房运维服务。 随着新能源的兴…...
线性代数学习
1.标量由只有一个元素的张量表示 import torchx torch.tensor([3,0]) y torch.tensor([2,0])x y, x * y, x / y, x**y 2.可以将向量视为标量值组成的列表 x torch.arange(4) x 3.通过张量的索引访问任一元素 x[3] 4.访问张量长度 len(x) 5.只有一个轴的张量,…...
FineReport 数据显示格式
原始 修改 选择「单元格元素>格式」,选择「日期型」,改成 「yyyy 年 MM 月 dd 日」,如下图所示: 注:若列表中没有 yyyy 年 MM 月 dd 日 格式,可手动输入 选择运货费数据列单元格,选择「单元…...
leetcode.204.计数质数
#中等#枚举 给定整数 n ,返回 所有小于非负整数 n 的质数的数量 。 埃氏筛 枚举没有考虑到数与数的关联性,因此难以再继续优化时间复杂度。接下来我们介绍一个常见的算法,该算法由希腊数学家厄拉多塞(Eratosthenes)提…...
Mysql环境安装
1,下载压缩包 下载压缩包解压 2,配置环境变量 i,高级系统设置-->环境变量-->系统变量-->path-->添加mysql的bin目录路径 ii,新建my.ini文件 basedir:MYSQL的路径 datadir:这个data路径不用手动创建&am…...
请问平面仓系统的盘点如何做?
盘点流程 一、盘点任务生成 手动发起:仓库管理人员可以根据实际需要,在系统中手动发起库存盘点任务。例如,定期进行全盘、抽盘或者在发现库存数据异常时发起盘点。自动触发:系统可以设置自动触发盘点的条件,如每隔一…...
STM32笔记(1)GPIO之点亮LED
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 总结 第一步:先看原理图。PB0输出高电平是,LED1点亮。 初始化完成了两项工作: (1)从时钟上启动所用GPIO所在的总线;…...
自动化工具
自动化工具确保测试准确性的关键在于采取一系列综合性措施,包括但不限于以下几点: 环境一致性:确保测试环境与生产环境尽可能相似,减少环境差异导致的结果不准确。可以通过容器技术(如Docker和Kubernetes)确…...
CTFHUB技能树之HTTP协议——响应包源代码
开启靶场,打开链接: 是个贪吃蛇小游戏,看不出来有什么特别的地方 用burp抓包看看情况: 嗯?点击“开始”没有抓取到报文,先看看网页源代码是什么情况 居然直接给出flag了,不知道这题的意义何在 …...
Java会话技术,拦截器,过滤器,登录校验
目录 1.会话: 2.会话跟踪: 3.会话跟踪方案: 客户端会话跟踪技术:Cookie 服务端会话跟踪技术:Session JWT令牌技术(https://jwt.io/) 定义: 优点: 缺点: 组成: …...
Spring Security 如何进行权限验证
阅读本文之前,请投票支持这款 全新设计的脚手架 ,让 Java 再次伟大! FilterSecurityInterceptor FilterSecurityInterceptor 是负责权限验证的过滤器。一般来说,权限验证是一系列业务逻辑处理完成以后,最后需要解决的…...
计算机砖头书的学习建议
纸上得来终觉浅,绝知此事要躬行,技术来源于实践,光看不练意义不大,过阵子全忘记,并且没有实践来深化理论认知。 “砖头书”通常指的是那些厚重、内容详实且权威的书籍,对于计算机科学领域而言,…...
我与C语言二周目邂逅vlog——7.预处理
C语言预处理详解 C语言预处理是编译过程中的重要组成部分,用于对源代码进行文本替换和修改。预处理发生在编译的前期,通过特定的指令来控制代码的编译行为,最终生成可以交给编译器进行进一步处理的代码。预处理的目的是简化代码编写…...
Python无监督学习中的聚类:K均值与层次聚类实现详解
📘 Python无监督学习中的聚类:K均值与层次聚类实现详解 无监督学习是一类强大的算法,能够在没有标签的数据集中发现结构与模式。聚类作为无监督学习的重要组成部分,在各类数据分析任务中广泛应用。本文将深入讲解聚类算法中的两种…...
C++ 中 new 和 delete 详解,以及与 C 中 malloc 和 free 的区别
1. C 中 new 和 delete 的基本用法 在 C 中,new 和 delete 是用来动态分配和释放内存的关键字,它们是面向对象的替代方式,提供了比 C 语言更优雅的内存管理工具。 1.1 new 的使用 new 用于从堆中分配内存,并且自动调用对象的构造…...
YOLOv11来了 | 自定义目标检测
概述 YOLO11 在 2024 年 9 月 27 日的 YOLO Vision 2024 活动中宣布:https://www.youtube.com/watch?vrfI5vOo3-_A。 YOLO11 是 Ultralytics YOLO 系列的最新版本,结合了尖端的准确性、速度和效率,用于目标检测、分割、分类、定向边界框和…...
Vue3 集成Monaco Editor编辑器
Vue3 集成Monaco Editor编辑器 1. 安装依赖2. 使用3. 效果 Monaco Editor (官方链接 https://microsoft.github.io/monaco-editor/)是一个由微软开发的功能强大的在线代码编辑器,被广泛应用于各种 Web 开发场景中。以下是对 Monaco Editor 的…...
一文详解Mysql索引
背景 索引是存储引擎用于快速找到一条记录的数据结构。索引对良好的性能非常关键。尤其是当表中的数据量越来越大时,索引对性能的影响愈发重要。接下来,就来详细探索一下索引。 索引是什么 索引(Index)是帮助数据库高效获取数据的…...
如何绕过iOS 15-16激活锁:AppleRa1n工具实战指南
如何绕过iOS 15-16激活锁:AppleRa1n工具实战指南 【免费下载链接】applera1n icloud bypass for ios 15-16 项目地址: https://gitcode.com/gh_mirrors/ap/applera1n 当你的iPhone或iPad因遗忘Apple ID密码、二手交易或维修后无法激活时,设备瞬间…...
救命!这些毕设太好抄了,3000+毕设案例推荐第1027期
271、基于Java的建材租赁智慧管理系统的设计与实现(论文+代码+PPT)建材租赁智慧管理系统主要功能包括:会员操作、客户资料、建材管理、计量单位、建材损坏收费标准、租赁合同、租费标准、租出登记、归还登记、丢赔管理、入库登记、租金计算、…...
新手福音:在快马平台跟随交互式教程轻松搞定openclaw安装
最近在学习openclaw这个工具时,发现很多教程要么太简略,要么步骤不完整,对新手特别不友好。后来在InsCode(快马)平台上发现可以创建交互式教程项目,就尝试做了一个完整的openclaw安装指南。整个过程比我预想的顺利很多,…...
锐龙处理器终极调优指南:如何用RyzenAdj释放隐藏性能
锐龙处理器终极调优指南:如何用RyzenAdj释放隐藏性能 【免费下载链接】RyzenAdj Adjust power management settings for Ryzen APUs 项目地址: https://gitcode.com/gh_mirrors/ry/RyzenAdj 你是否曾觉得自己的AMD锐龙处理器性能没有完全发挥?或者…...
[推荐]生产环境部署: docker+gitea+jenkins+jenkinsfile+ansible+钉钉 实现多机批量部署及其推送通知
1)打包机: giteapostgres、jenkins软件安装 (注意jenkins镜像中自动安装python和ansible环境)mkdir data, 在此目录下放好docker-compose.yml然后用docker compose up -d 在打包机部署好环境 其它工作机器什么都不用做后续都是用ansible自动完成!!![rootlocalhost soft]# cat d…...
Topit:5倍提升多任务效率的macOS窗口置顶神器
Topit:5倍提升多任务效率的macOS窗口置顶神器 【免费下载链接】Topit Pin any window to the top of your screen / 在Mac上将你的任何窗口强制置顶 项目地址: https://gitcode.com/gh_mirrors/to/Topit Topit是一款专为macOS用户设计的开源窗口管理工具&…...
HoRNDIS:Mac与Android USB网络共享终极指南
HoRNDIS:Mac与Android USB网络共享终极指南 【免费下载链接】HoRNDIS Android USB tethering driver for Mac OS X 项目地址: https://gitcode.com/gh_mirrors/ho/HoRNDIS 想在Mac上使用Android手机的USB网络共享功能吗?HoRNDIS这款免费开源驱动就…...
终极指南:掌握 oh-my-posh2 主题设计原理与最佳实践
终极指南:掌握 oh-my-posh2 主题设计原理与最佳实践 【免费下载链接】oh-my-posh2 A prompt theming engine for Powershell 项目地址: https://gitcode.com/gh_mirrors/oh/oh-my-posh2 oh-my-posh2 是一个强大的 PowerShell 主题引擎,能够为你的…...
3分钟掌握Mem Reduct:让你的Windows内存管理说中文
3分钟掌握Mem Reduct:让你的Windows内存管理说中文 【免费下载链接】memreduct Lightweight real-time memory management application to monitor and clean system memory on your computer. 项目地址: https://gitcode.com/gh_mirrors/me/memreduct 还在为…...
vscode-react-native终极入门指南:5分钟搭建React Native开发环境
vscode-react-native终极入门指南:5分钟搭建React Native开发环境 【免费下载链接】vscode-react-native VSCode extension for React Native - supports debugging and editor integration 项目地址: https://gitcode.com/gh_mirrors/vs/vscode-react-native …...
