这是一份基于匿名管道实现的进程池代码,供学习参考
cpp
#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "Task.hpp"
// master
class Channel
{
public:
Channel(int wfd, pid_t id, const std::string &name) : _wfd(wfd), _id(id), _name(name)
{
}
int Getwfd()
{
return _wfd;
}
int Getid()
{
return _id;
}
std::string &Getname()
{
return _name;
}
static int NextChannel(int num)
{
static int next = 0;
int ret = next;
next++;
return ret % num;
}
void Close(){
::close(_wfd);
}
~Channel()
{
}
private:
int _wfd;
pid_t _id;
std::string _name;
};
void clean(std::vector<Channel> &Ch)
{
for (auto &e : Ch)
{
close(e.Getwfd());
}
for (auto &e : Ch)
{
waitpid(e.Getid(), nullptr, 0);
}
}
void CreateChannel(std::vector<Channel> &channels, int num, task_t task)
{
for (int i = 0; i < num; i++)
{
int pipefd[2]; // 管道
if (pipe(pipefd) < 0)
exit(1);
pid_t id = fork();
if (id == 0)
{
if (!channels.empty())
{
for(auto & channel : channels) channel.Close();
}
// worker;
close(pipefd[1]); // close w ---> r
dup2(pipefd[0], 0); // 重定向
task();
exit(0);
}
close(pipefd[0]); // w
channels.emplace_back(pipefd[1], id, "Channel-" + std::to_string(i));
}
}
void SendTaskCommend(Channel &ch, int task)
{
write(ch.Getwfd(), &task, sizeof(task));
}
void ctrlProcess(std::vector<Channel> &channels, int num, size_t times = 10)
{
while (times--)
{
// 选择任务
int task = SelectTask();
// 选择进程
int ch = Channel::NextChannel(num);
// 发送
SendTaskCommend(channels[ch], task);
// 回收进程
sleep(1);
}
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
std::cout << "Usage: " << argv[0] << "processnum" << std::endl;
return 1;
}
int num = std::stoi(argv[1]);
std::vector<Channel> channels;
InitTask();
// 创建
CreateChannel(channels, num, worker);
// 控制,分配任务
ctrlProcess(channels, num);
// 回收
clean(channels);
return 0;
}
Task.hpp
cpp
#pragma once
#include <iostream>
#include <functional>
#include <ctime>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#define TaskNum 3
// typedef void (*task_t)();
using task_t = std::function<void()>;
void Print()
{
std::cout<< "I am Print Task" << std::endl;
}
void DownLoad()
{
std::cout<< "I am DownLoad Task" << std::endl;
}
void Flush()
{
std::cout<< "I am Flush Task" << std::endl;
}
task_t tasks[TaskNum];
void InitTask()
{
srand(time(nullptr) ^ getpid());
tasks[0] = Print;
tasks[1] = DownLoad;
tasks[2] = Flush;
}
void ExcuteTask(int num)
{
tasks[num]();
}
int SelectTask()
{
return rand() % TaskNum;
}
void worker()
{
while(true) {
int command = 0;
// 卡在read了
int i = read(0, &command, sizeof(command));
if(i == 0) {
std::cout<<getpid()<<" quit "<<std::endl;
break;
}
ExcuteTask(command);
}
}