main.cpp
cpp
#include"Task.hpp"
#include<iostream>
#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;
const int num=10;
vector<task_t> tasks;
class channel
{
public:
int _cmdfd; //发送任务的文件符
pid_t _childpid; //子进程的pid
string _process_name; //子进程的名字
public:
channel(int cmdfd,pid_t childpid,string process_name)
:_cmdfd(cmdfd)
,_childpid(_childpid)
,_process_name(process_name)
{}
};
void child()//子进程接收任务并执行任务
{
while(true)
{
int taskcode=0;
ssize_t ret=read(0,&taskcode,sizeof(int));//读取任务编号
if(ret==sizeof(int))
{
cout<<"child alread get a task: "<<getpid()<<" : taskcode : "<< taskcode<<endl;
tasks[taskcode]();//根据任务编号执行任务
}
if(ret==0)
{
break;
}
}
}
void Initprocesspool(vector<channel> *channels)
{
vector<int> v;//存储父进程的写端
for(int i=0;i<num;i++)
{
int pipefd[2];
int ret=pipe(pipefd);
pid_t id=fork();
if(id==0)
{
//child
for(auto &it:v) close(it);//当创建子进程时,此时会继承父进程和上一个子进程的管道写端,需要关闭对上一个子进程的写端
close(pipefd[1]);//关闭写端
dup2(pipefd[0],0);//将0号文件描述符重定向到管道文件,从0号文件描述符写的信息会被重定向到管道文件
child();//子进程去执行任务
close(pipefd[0]);//关闭读端
exit(0);
}
close(pipefd[0]);//关闭读端
string name="process"+to_string(i);
channels->push_back(channel(pipefd[1],id,name));//存储子进程的信息
v.push_back(pipefd[1]);//将父进程的写端插入
}
}
void Debug(vector<channel> &channels)//打印所有子进程的信息
{
for(auto it:channels)
{
cout<<it._childpid<<" "<<it._cmdfd<<" "<<it._process_name<<" "<<endl;
}
}
void menu()
{
cout<<"###############################################"<<endl;
cout<<"1. 打篮球 2.踢足球"<<endl;
cout<<"3. 打羽毛球 4.打乒乓球"<<endl;
cout<<" 0.退出 "<<endl;
cout<<"###############################################"<<endl;
}
void ctrlchild(vector<channel>&channels)
{
while(true)
{
int select=0;
menu();
cout<<"please choose: ";
cin>>select;//输入选择的任务序号
int processpos=0;//进程编号
int taskcode=select-1;//选择的序号减一才是存储任务的指针数组的下标
if(select>0&&select<=4)
{
cout<<"father say "<<"taskcode: "
<<taskcode<<"already send to: "<<channels[processpos]._childpid
<<"process name: "<<channels[processpos]._process_name<<endl;
ssize_t n=write(channels[processpos]._cmdfd,&taskcode,sizeof(taskcode));//将存储任务的指针数组的下标写入指定的管道文件
}
else
{
break;
}
}
}
void quitprocess(vector<channel>&channels)
{
for(const auto &it:channels)
{
close(it._cmdfd);//关闭所有子进程的读端
waitpid(it._childpid,nullptr,0);//回收子进程
}
}
int main()
{
Loadtask(&tasks);
vector<channel> channels;
//初始化
srand(time(nullptr));
Initprocesspool(&channels);
Debug(channels);
//开始控制子进程
ctrlchild(channels);
quitprocess(channels);
return 0;
}
Task.hpp
cpp
#pragma once
#include<iostream>
#include<vector>
using namespace std;
typedef void (*task_t)();
void task1()
{
cout<<"打篮球"<<endl;
}
void task2()
{
cout<<"踢足球"<<endl;
}
void task3()
{
cout<<"打羽毛球"<<endl;
}
void task4()
{
cout<<"打乒乓球"<<endl;
}
void Loadtask(vector<task_t>*tasks)
{
tasks->push_back(task1);
tasks->push_back(task2);
tasks->push_back(task3);
tasks->push_back(task4);
}
运行结果:
