一.何谓池化技术?
简单来说,就是创建并维护一个存放资源的"池子",然后一次性的申请大量的资源放在里面 ,当需要使用资源时,直接从池子里取,用完后再放回池子中,提升程序的效率。
二.理解进程池
父进程一次性创建出一批子进程和管道,这个体系就叫做进程池。
父进程每次向匿名管道写入不同内容,然后通过发送不同任务码(int code),进而操作不同的子进程完成不同的读操作。
根据写快,读慢的通信情况,只要父进程不写东西,子进程就会阻塞住,一直等待父进程。当父进程一写东西,子进程的阻塞就会被打断,进而去读取;父进程通过对写操作的继续与停止,进而导致子进程阻塞的停止与继续 ,这样的操作叫做唤醒和暂停子进程。

三.实现
用下标_next++即可完成管道的轮询,用整数code的地址作为buffer,保证一次读/写四个字节(code)。
#pragma once
#include<iostream>
#include<vector>
#include<unistd.h>
#include<cstdlib>
#include<sys/wait.h>
class Channel
{//管道类,先描述
public:
Channel(int fd,pid_t pid)
:_wfd(fd)
,subid(pid)
{
_name = "channel-" + std::to_string(_wfd) + "-" + std::to_string(pid);
}
~Channel()
{}
void Send(int code)
{
int n = write(_wfd,&code,sizeof(code));
(void)n;//使用一下,防止警告
}
int Fd(){return _wfd;}
pid_t SubId(){return subid;}
std::string Name(){return _name;}
void Close()
{
close(_wfd);
}
void Wait()
{
pid_t rid = waitpid(subid,nullptr,0);
(void)rid;
}
private:
int _wfd;
pid_t subid;
std::string _name;
};
//管理管道的类,再组织
class ChannelManager
{
public:
ChannelManager()
:_next(0)
{}
~ChannelManager()
{}
void Build(int wfd,pid_t subid)
{
Channel c(wfd,subid);
_channels.push_back(c);
}
void PrintChannel()
{
for(auto &channel: _channels)
{
std::cout << channel.Name() << std::endl;
}
}
Channel& Selct()
{
auto &c = _channels[_next];
++_next;
_next %= _channels.size();//防止越界
return c;
}
void StopProcess()
{
for(auto &channel:_channels)
{
channel.Close();
}
}
void WaitProcess()
{
for(auto &channel:_channels)
{
channel.Wait();
}
}
private:
std::vector<Channel> _channels;
int _next;
};
const int gdefaultnum = 5;//创建子进程的数量
class ProcessPool
{
public:
ProcessPool(int num)
:_Process_nms(num)
{}
~ProcessPool()
{}
void Work(int rfd)
{
while(true)
{
int code = 0;
ssize_t n = read(rfd,&code,sizeof(code));
if(n > 0)
{//读取成功
//必须按规范,一次读取四个字节的数据。
if(n != sizeof(code))
{
continue;
}
else
{
std::cout << "子进程[" << getpid() << "]收到一个任务码:" << code << std::endl;
}
}
else if(n == 0)
{//父进程写端关闭,子进程退出
std::cout << "子进程退出" << std::endl;
break;
}
else
{//读取失败
std::cout << "读取失败" << std::endl;
break;
}
}
}
bool Create()
{
for(int i = 0;i < _Process_nms;++i)
{
//1.创建管道
int pfd[2] = {0};
int n = pipe(pfd);
if(n < 0) return false;
//2.创建进程
pid_t subid = fork();
if(subid < 0) return false;
else if(subid == 0)//父写子读
{//子进程
//3.关闭不需要的fd
close(pfd[1]);
//4.读取
Work(pfd[0]);
//5.关所有的fd
close(pfd[0]);
exit(0);
}
else
{//父进程
//3.关闭不需要的fd
close(pfd[0]);
_cm.Build(pfd[1],subid);
}
}
return true;
}
void debug()
{
_cm.PrintChannel();
}
void TaskPush(int task_code)
{
//1.选择一个信道,负载均衡的选择一个子进程,完成任务。
//这里选择轮询来实现均衡。
auto &c = _cm.Selct();//用下标_next来控制轮询。
//2.发送(写入)数据
c.Send(task_code);
std::cout << "发送一个任务码:" << task_code << std::endl;
}
void Stop()
{
//关闭父进程的所有wfd,就可以停掉所有子进程
_cm.StopProcess();
//回收子进程
_cm.WaitProcess();
}
private:
ChannelManager _cm;
int _Process_nms;//进程数量
};