概念
进程池其实就是我们提前创建好一批进程, 当有任务的时候再将进程指派过去完成那个任务。
中间的这框框就是管道, 当父进程没有给子进程发送任务的时候, 子进程就会一直阻塞着, 于是就形成了这样的结构。
代码
#include "ProcessPool.hpp"
#include <cassert>
#include <ctime>
const int processnum = 5;
class channel {
public:
channel(int cmdfd, int pid, const std::string& processname)
:_cmdfd(cmdfd), _slaverid(pid), _processname(processname)
{ }
int _cmdfd; // 文件描述符
pid_t _slaverid; // 子进程的pid
std::string _processname; // 子进程的名字
};
void slaver()
{
// read(0)
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;
}
}
void InitProcessPool(std::vector<channel> *channels)
{
// version 2: 确保每一个子进程都只有一个写端
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) // child
{
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);
close(pipefd[0]);
slaver();
std::cout << "process : " << getpid() << " quit" << std::endl;
// slaver(pipefd[0]);
exit(0);
}
// father
close(pipefd[0]);
// 添加channel字段了
std::string name = "process-" + std::to_string(i);
channels->push_back(channel(pipefd[1], id, name));
oldfds.push_back(pipefd[1]);
sleep(1);
}
}
void debug(const std::vector<channel>& channels) {
for (auto e : channels) {
std::cout << e._cmdfd << ' ' << std::endl;
}
}
void ctrlSlaver(const std::vector<channel> &channels)
{
int which = 0;
// int cnt = 5;
while(true)
{
int select = 0;
std::cout << "Please Enter@ ";
std::cin >> select;
if(select <= 0 || select >= 5) break;
// select > 0&& select < 5
// 1. 选择任务
// int cmdcode = rand()%tasks.size();
int cmdcode = select - 1;
// 2. 选择进程
// int processpos = rand()%channels.size();
std::cout << "father say: " << " cmdcode: " <<
cmdcode << " already sendto " << channels[which]._slaverid << " process name: "
<< channels[which]._processname << std::endl;
// 3. 发送任务
write(channels[which]._cmdfd, &cmdcode, sizeof(cmdcode));
which++;
which %= channels.size();
// cnt--;
// sleep(1);
}
}
int main()
{
srand(time(nullptr)^getpid()^1023); // 种一个随机数种子
// 在组织
std::vector<channel> channels;
// 1. 初始化 --- bug?? -- 找一下这个问题在哪里?然后提出一些解决方案!
InitProcessPool(&channels);
// Debug(channels);
// 2. 开始控制子进程
ctrlSlaver(channels);
// 3. 清理收尾
return 0;
}