当前位置: 首页 > news >正文

匿名管道--任务派发程序

整体代码逻辑架构图如下:

整体架构图如下:

整体代码如下:

main.cc:

#include "processpool.hpp" #include "Tasks.hpp" int main(int argc, char *argv[]) { if(argc!=2){ cout<<"Usage: "<<argv[0]<<" <process_num>"<<endl; return -1; } int process_num = stoi(argv[1]); proc_pool *pool = new proc_pool(process_num, worker); //初始化进程池 pool->Initproc_pool(); //分发任务 pool->Dispatch_task(); sleep(3); //打印进城池 pool->Print(); //清空进程池 pool->Delete_proc_pool(); delete pool; return 0; }

processpool.hpp:

#ifndef PROCESSPOOL_HPP #define PROCESSPOOL_HPP #include <iostream> #include <vector> #include <functional> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <string> #include "Tasks.hpp" using namespace std; using work_t = function<void()>; // 定义函数指针类型 enum : int { OK, FORK_ERROR, PIPE_ERROR, READ_ERROR, WRITE_ERROR, EXIT_ERROR }; // 先描述 class channel { public: channel(int procfd, pid_t who) : _procfd(procfd), who(who) {} // 构造函数 ~channel() {} string Name() { return name = "channel_" + to_string(who) + "-" + to_string(_procfd); // 获取子进程名 } // 4个get函数 void send(int cmd) { ::write(_procfd, &cmd, sizeof(cmd)); // 发送命令 } bool Close() { if (_procfd < 0) return true; if (::close(_procfd) == -1) { perror("close"); return false; } _procfd = -1; // 文件描述符必定大于0,因此-1无效 return true; } pid_t Id() { return who; // 获取子进程id } int procid() { return _procfd; // 获取管道fd } private: int _procfd; string name; pid_t who; }; // 再组织 class proc_pool { public: proc_pool(int n, work_t work) : _work(work), proc_num(n) { } ~proc_pool() { } int Initproc_pool() { // 创建n个子进程 for (int i = 0; i < proc_num; ++i) { // 1.创建管道 int pipefd[2]; int n = pipe(pipefd); if (n < 0) { return PIPE_ERROR; // 管道创建失败 } // 2.创建父子进程 pid_t pid = fork(); if (pid < 0) { return FORK_ERROR; // 创建进程失败 } if (pid == 0) { // 子进程关闭历史fd for (auto &ch : _channels) { cout << "已关闭: _procfd=" << ch.procid() << endl; ch.Close(); } // 子进程关闭写端 ::close(pipefd[1]); cout << "子进程获取到读端fd: " << pipefd[0] << endl; // 子进程重定向标准输入为读端 dup2(pipefd[0], 0); // 子进程开始完成父进程分发的随机任务 worker(); // 子进程退出 _exit(OK); // 子进程退出 } // 3.父进程关闭读端,子进程关闭写端 ::close(pipefd[0]); // 4.父进程保存子进程id和管道fd _channels.emplace_back(pipefd[1], pid); } return OK; } void Dispatch_task() { int who = 0; int num = 20; while (num--) { // 1.选择一个任务 int taskcode = tasks.Task_select(); // 2.选择一个子进程管道 // 先给管道内部成员起别名,方便操作 channel &ch = _channels[who++ % proc_num]; sleep(1); cout << "父进程分发任务码:" << taskcode << ch.Name() << endl; cout << "任务还剩: " << num << " 个" << endl; // 3.发送任务码给子进程 ch.send(taskcode); } } void Delete_proc_pool() { // 删除管道 for (auto &ch : _channels) { bool ret=ch.Close();//close后,写端关闭,子进程读取到EOF,退出循环,退出子进程 pid_t pid = waitpid(ch.Id(), nullptr, 0); // 等待子进程退出 if(ret==true&&pid>0){ cout << "子进程退出成功,ID=" << pid << endl; } else{ cout << "子进程退出失败,ID=" << pid << endl; } } } void Print(){ for (auto &ch : _channels) { cout << "进程池元素正在循环打印中:" << ch.Name() << endl; } } private: vector<channel> _channels; work_t _work; int proc_num; }; #endif

Tasks.hpp:

#ifndef TASKS_HPP #define TASKS_HPP #include <iostream> #include <vector> #include <functional> #include <unistd.h> #include <sys/types.h> #include <ctime> using namespace std; using task_t=function<void()>; // 定义函数指针类型 class Tasks { public: Tasks() { srand(time(NULL)); task_queue.push_back([](){cout<<getpid()<<" :进程"<<"任务1"<<endl;}); task_queue.push_back([](){cout<<getpid()<<" :进程"<<"任务2"<<endl;}); task_queue.push_back([](){cout<<getpid()<<" :进程"<<"任务3"<<endl;}); task_queue.push_back([](){cout<<getpid()<<" :进程"<<"任务4"<<endl;}); } ~Tasks() {} //随机选择任务码 int Task_select(){ return rand()%task_queue.size(); } //执行vector函数队列中的任务 void Execute_task(unsigned long int num){ if(num < task_queue.size()||num<0) { task_queue[num](); } else { cout<<"任务码不存在"<<endl; } } private: vector<task_t> task_queue; }; //任务对象 Tasks tasks; //子进程进行完成任务 void worker(){ while (true) { int cmd=0; // 从管道读取任务码,直接拿pipefd是拿不到的,所以之前dup2重定向了标准输入,所以这里直接从标准输入读取 int n= read(0, &cmd, sizeof(cmd)); if(n == 0) { cout<<"子进程: "<<getpid()<<"读取到文件EOF"<<endl; break; // 读取失败,退出循环 } else { tasks.Execute_task(cmd); } } } #endif

Makefile:

SRC=$(wildcard *.cc) OBJ=$(SRC:.cc=.o) BIN=pipe $(BIN):$(OBJ) g++ -o $@ $^ %.o:%.cc g++ -c $< .PHONY:clean clean: rm -rf $(BIN) $(OBJ) .PHONY:test test: @echo $(SRC) @echo $(OBJ)
http://www.jsqmd.com/news/1286007/

相关文章:

  • B站字幕提取全攻略:从手动抓包到Python自动化脚本实现
  • agent多层调用
  • 江门漏水检测正规公司推荐-同城防水补漏免砸砖维修-暗管漏水精准定位-卫生间-屋顶-阳台-厨房-地下室渗漏综合治理指南 - 知途管道科技
  • 技术人做专利转让,我是怎么选平台的?
  • 2026年AI技术老师挑选全指南:4步筛选法帮你选到靠谱落地导师
  • DSTE咨询洞察:读懂华为BLM底层逻辑:别再只把它当战略模板套用
  • DIY蓝牙公仔音响:从模块拆解到手工缝合的完整制作指南
  • Arduino/ESP32智能小车摇头避障:从硬件选型到算法优化的完整指南
  • 医院在开展医学新技术转化时,合规的知识产权评估和授权步骤有哪些?
  • 河源漏水检测公司推荐-同城防水补漏维修-暗管漏水精准定位-卫生间-屋顶-阳台-厨房-地下室渗漏检测与修复指南 - 知途管道科技
  • 呼和浩特漏水检测公司推荐-暗管测漏精准定位-卫生间-厨房-屋顶-阳台-地下室防水补漏免砸砖维修指南 - 知途管道科技
  • 如何从零开始成为一名智能体人工智能工程师
  • NVIDIA Profile Inspector:解锁显卡隐藏性能的完整指南
  • 精拔无缝钢管供应商怎么样 - 品牌推广大师
  • C++素数判断算法:从朴素试除法到6k±1优化详解
  • SpringBoot防疫物资管理系统设计与实现
  • 嵌入式开发实战:深度解析Cortex-M内核PPA(性能、功耗、面积)分析与选型
  • PMP 培训哪家靠谱?2026 主流 PMP 培训机构全面对比与择校指南,项目生命周期重要考点讲解
  • 国家对于公立医疗机构科技成果转化有哪些最新的政策支持或认定标准?
  • 炉石传说插件HsMod:如何用55项功能彻底改变你的游戏体验
  • 徐州家装行业深度测评报告|五大品牌施工服务本地化能力横向对比
  • STM32标准库开发:从零搭建模块化工程目录与Keil配置指南
  • 2026镇江漏水检测公司推荐-暗管测漏精准定位-卫生间-厨房-屋顶-阳台-地下室防水补漏免砸砖维修 - 知途管道科技
  • 2026东营漏水维修全攻略,卫生间/阳台/外墙/屋顶/地下室对症方案+靠谱商家推荐 - 苏易房屋修缮
  • AI教材编写工具:提升效率与降低查重率的实践指南
  • DIY超声波清洗器:从空化效应原理到驱动电路实战指南
  • 天津漏水检测正规公司推荐:同城防水补漏免砸砖维修-暗管漏水精准定位-卫生间-屋顶-阳台-厨房-地下室渗漏综合治理指南 - 知途管道科技
  • GEO风险全景图:合规、隐私与算法波动应对
  • 国内专业的P-DUKE电源分销商
  • OpenClaw:AI如何革新技术需求文档编写