#include<iostream>
#include<vector>
#include<string>
#include<cstring>
#include<cstdlib>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/wait.h>
//把5个子进程要管理起来,要先描述再组织
const int processnum=5;
//先描述
class channel
{
public:
channel(pid_t slaverpid,int cmdfd,std::string slavername)
:_slaverpid(slaverpid),_slavername(slavername),_cmdfd(cmdfd)
{}
public:
pid_t _slaverpid;//子进程pid
int _cmdfd;//发送任务的文件描述符
std::string _slavername;//子进程的名字,方便打印日志
};
void Slaver()
{
while(true)
{
int cmdnode=0;
int n=read(0,&cmdnode,sizeof(int));
if(n==sizeof(int))
{
std::cout<<std::endl;
std::cout <<"slaver say@ get a command: "<< " cmdcode: " << cmdnode << std::endl;
//执行任务列表
switch(cmdnode)
{
case 1:
{
std::cout<<"刷新野怪"<<std::endl;
break;
}
case 2:
{
std::cout<<"购买装备"<<std::endl;
break;
}
case 3:
{
std::cout<<"释放技能"<<std::endl;
break;
}
case 4:
{
std::cout<<"查看战绩"<<std::endl;
break;
}
}
}
if(n==0) break;
}
}
void Initprocesspool(std::vector<channel>& channels)
{
std::vector<int> oldwfd;//用来存储旧的写端fd, 确保每一个子进程都只有一个写端
for(int i=0;i<processnum;i++)
{
int pipefd[2]={0};
int n=pipe(pipefd);
if(n<0) return ;
pid_t id=fork();
if(id==0) //child
{
for(auto& fd:oldwfd) close(fd);//关闭从父进程继承下来的写端
close(pipefd[1]);
dup2(pipefd[0],0);//把标准输入重定向到读端文件,简化代码,可以不这么写
Slaver();
close(pipefd[0]);
exit(0);
}
close(pipefd[0]);
//添加channel字段
std:: string name="process-"+std::to_string(i);
channels.push_back(channel(id,pipefd[1],name));
oldwfd.push_back(pipefd[1]);
}
}
void Debug(const std::vector<channel> &channels)
{
// test
for(const auto &c :channels)
{
std::cout << c._cmdfd << " " << c._slaverpid << " " << c._slavername << std::endl;
}
}
void menu()
{
std::cout<<"###########################################"<<std::endl;
std::cout<<"###### 1.刷新野怪 2.购买装备######"<<std::endl;
std::cout<<"###### 3.释放技能 4.查看战绩#######"<<std::endl;
std::cout<<"###### 0.退出 #######"<<std::endl;
std::cout<<"###########################################"<<std::endl;
}
void Ctrlprocess(std::vector<channel> channels)
{
while(true)
{
int select=0;
menu();
std::cout<<"please select@";
std::cin>>select;
if(select<1||select>4) break ;
//选择进程,随机选择
int processpos=rand()%channels.size();
std::cout<<"father say:"<<"select:"<<select<<" can todo "<<
channels[processpos]._slaverpid<<"slavername:"<<channels[processpos]._slavername<<std::endl;
//发放任务
write(channels[processpos]._cmdfd,&select,sizeof(select));
sleep(1);
}
}
void Quitprocess(const std::vector<channel>& channels)
{
for(const auto& process:channels)
{
close(process._cmdfd);
waitpid(process._slaverpid,nullptr,0);
}
}
int main()
{
srand(time(nullptr));
std::vector<channel> channels;
//1.初始化进程池
Initprocesspool(channels);
Debug(channels);
//2.控制子进程
Ctrlprocess(channels);
//3.清理收尾
Quitprocess(channels);
return 0;
}