运行效果:
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);
}
}