用匿名管道创建进程池

运行效果:

Task.hpp:

#pragma once

#include<iostream>
#include<string>
#include<vector>
#include<unordered_map>
#include<unistd.h>
#include<functional>

typedef std::function<void()> func;//也可以写using func = std::function<void()>

std::vector<func> callbacks;//存放任务函数
std::unordered_map<int,std::string> desc;//描述任务指令编号及信息

//任务
void readMySQL()
{
    std::cout << "sub process[" << getpid() << "] 执行访问数据库的任务\n" << std::endl;
}

void execulerUrl()
{
    std::cout << "sub process[" << getpid() << "] 执行url解析\n" << std::endl;
}

void cal()
{
    std::cout << "sub process[" << getpid() << "] 执行加密任务\n" << std::endl;
}

void save()
{
    std::cout << "sub process[" << getpid() << "] 执行数据持久化任务\n" << std::endl;
}

//加载任务
void load()
{
    desc.insert({callbacks.size(), "readMySQL: 读取数据库"});
    callbacks.push_back(readMySQL);
    
    desc.insert({callbacks.size(), "execulerUrl: 进行url解析"});
    callbacks.push_back(execulerUrl);

    desc.insert({callbacks.size(), "cal:进行加密计算"});
    callbacks.push_back(cal);

    desc.insert({callbacks.size(), "save:进行数据的文件保存"});
    callbacks.push_back(save);
}

//展示任务信息
void showHandler()
{
    for(const auto &iter : desc)
    {
        std::cout << iter.first << "\t" << iter.second << std::endl;
    }
}

int handlerSize()
{
    return callbacks.size();
}

ProcessPool.cc:

#include<iostream>
#include<vector>
#include<cassert>
#include<unistd.h>
#include<stdlib.h>
#include<ctime>
#include<sys/types.h>
#include<sys/wait.h>
#include"Task.hpp"

#define PROCESS_NUM 5

using namespace std;

int waitCommand(int waitFd, bool &quit)
{
    uint32_t command = 0;
    ssize_t s = read(waitFd, &command, sizeof(command));
    if(s == 0)
    {
        quit = true;
        return -1;
    }
    assert(s == sizeof(uint32_t));
    return command;
}

void sendAndWakeup(pid_t who, int fd, uint32_t command)
{
    write(fd, &command, sizeof(command));
    cout << "mian process: call process " << who << " execute " << desc[command] << " through " << fd << endl;
}

int main()
{
    load();
    //           pid : pipefd
    vector<pair<pid_t,int>> slots;
    //先创建多个进程
    for(int i = 0; i < PROCESS_NUM; i++)
    {
        //创建管道
        int pipefd[2] = {0};
        int n = pipe(pipefd);
        assert(n == 0);
        (void)n;

        pid_t id = fork();
        assert(id != -1);
        //让子进程进行读取
        if(id == 0)
        {
            //关闭写端
            close(pipefd[1]);
            //child
            while(true)
            {
                //等命令
                bool quit = false;//不退出
                int command = waitCommand(pipefd[0],quit);//如果对方不发命令,就阻塞
                if(quit) break;
                //执行对应的命令
                if(command >= 0 && command < handlerSize())
                {
                    callbacks[command]();
                }
                else
                {
                    cout << "非法command: " << endl;
                }
            }
            exit(1);
        }
        //father,进行写入,关闭读端
        close(pipefd[0]);
        slots.push_back(pair<pid_t,int>(id,pipefd[1]));
    }
    //父进程随机派发任务(负载平衡)
    srand((unsigned long)time(nullptr) ^ getpid() ^ 233236323L);//让数据源更随机
    while(true)
    {
        //让系统自动选
        //选择一个任务
        int command = rand()%handlerSize();
        //选择一个进程
        int choice = rand()%slots.size();
        //把任务给指定进程
        sendAndWakeup(slots[choice].first, slots[choice].second, command);
        sleep(1);

        // //自己选
        // int select;
        // int command;
        // cout << "------------------------------------------------------------" << endl;
        // cout << "###          1. show functions       2. send command     ###" << endl;
        // cout << "------------------------------------------------------------" << endl;
        // cout << "Please Select : ";
        // cin >> select;
        // if(select == 1) showHandler();
        // else if(select == 2)
        // {
        //     cout << "Enter Your Command: ";
        //     //选择任务
        //     cin >> command;
        //     //选择进程
        //     int choice = rand()%slots.size();
        //     //把任务给指定进程
        //     sendAndWakeup(slots[choice].first, slots[choice].second, command);
        // }
        // else
        // {
        //     break;
        // }
    }
    //关闭fd,结束所有进程
    for(const auto& slot : slots)
    {
        close(slot.second);
    }

    //回收所有子进程信息
    for(const auto& slot : slots)
    {
        waitpid(slot.first,nullptr,0);
    }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值