简易版的进程池

1.使用匿名管道实现 进程池

#pragma once

typedef void(*task_t)();

void task1()
{
	cout << "游戏 刷新日志" << endl;
}

void task2()
{
	cout << "游戏 刷新野区" << endl;
}
void task3()
{
	cout << "游戏 检测软件是否更新,如果需要,就提示用户" << endl;
}
void task4()
{
	cout << "游戏 用户释放技能,更新用户的HP和MP"<<endl;
}
void Loadtask(vector<task_t> *tasks)
{
	tasks->push_back(task1);
	tasks->push_back(task2);
	tasks->push_back(task3);
	tasks->push_back(task4);
}

//以上是头文件

//以下是程序;
//类似于内存池,每次使用都不再向系统申请进程,而是提前储备进程;
#include<cstdlib>
#include<cassert>
#include<time.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<iostream>
#include<vector>
#include<string>
#include<unistd.h>

using namespace std;
#include"main.h"
const int processnum = 5;//子进程数量=5
vector<task_t> tasks;  //任务列表,全局变量

//先描述
class channel
{
public:
	channel(int cmdfd ,pid_t slaverid,const string &processname)
		:_cmdfd(cmdfd),
		_slaverid(slaverid),
		_processname(processname)
	{}
public:
	int _cmdfd;	//发送任务的文件描述符
	pid_t _slaverid; //子进程的pid
	string _processname;//子进程的名字——方便我们打印日志;
};

void slaver()
{
	//read(0);//直接从标准输入读
	while (true)
	{
		int cmdcode = 0;
		int n = read(0,&cmdcode,sizeof(int));//如果父进程不给子进程发任务?就会阻塞等待;
		if (n == sizeof(int))
		{
			//执行cmdcode 对应的任务列表;
			cout << getpid() << ":cmdcode:" << cmdcode << endl;//查看父进程给子进程派发的任务码;
			if (cmdcode > 0 && cmdcode < tasks.size()) //满足条件运行函数;
				tasks[cmdcode]();
		}
		if (n == 0)
		{
			break;
		}
	}
}
//函数传参,需要输入型,输出型,输入输出型参数;
//输入:const &: const引用
//输出:用指针
//输入输出:&引用
void InitProcessPool(vector<channel>* channels)
{
	//方法二:确保,每个子进程都只有一个写端
	vector<int> oldfds;
	//1.初始化
	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)//子进程读
		{
			for (auto fd : oldfds) close(fd);			//关掉写端管道;
			close(pipefd[1]);
			dup2(pipefd[0], 0);							//重定向,从标准输入中读
			close(pipefd[0]);
			slaver();									//执行相对应的任务;
			cout << "process: " << getpid() << "quit" << endl;//打印子进程pid;退出进程;
			exit(0);
		}
		//父进程写入
		close(pipefd[0]);

		//添加channel字段;
		string name = "process-" + to_string(i);
		channels->push_back(channel(pipefd[1], id, name));
		oldfds.push_back((pipefd[1]));
	}
}
void Debug(const vector<channel> &channels)
{
	//test
	for (const auto& c : channels)
	{
		cout << c._cmdfd << " " << c._slaverid << " " << c._processname << endl;
	}
}
void Menu()											//菜单
{
	cout << "1.刷新日志" << endl;
	cout << "2.刷新野怪" << endl;
	cout << "3.检测更新" << endl;
	cout << "4.更新状态" << endl;
	cout << "0.退出游戏" << endl;
}
//控制子进程
void ctrlSlaver(const vector<channel>& channels)
{
	int which = 0;
	//int cnt = 5;
	while(true)
	{
		int select = 0;
		Menu();                              //手动控制
		cout << "please Enter@" << endl;
		cin >> select;

		if (select <= 0 || select >= 5) break;
		//select >0 &&select<5
		
		//1.选择任务
		//int cmdcode = rand() % tasks.size();//创造一个随机数,当作任务;
		int cmdcode = select-1;

		//2.选择进程(负载均衡:不可以一直给某个进程派发任务,其他进程都闲着,要均衡发展这个叫做负载均衡)1.使用随机数  2.轮转l来实现负载均衡
		
		//int processpos = rand() % channels.size();						//随机数
		//cout << "father say:" << "cmdcode:" << cmdcode << "already send to" << channels[processpos]._slaverid << endl;

		cout << "father say:" << "cmdcode:" << cmdcode << "already send to" << channels[which]._slaverid << endl;//轮转

		//3.发送任务
		//write(channels[processpos]._cmdfd, &cmdcode, sizeof(cmdcode));      //随机数版本
		write(channels[which]._cmdfd, &cmdcode, sizeof(cmdcode));			  //轮转
		which++;
		which %= channels.size();
		//cnt--;
		//sleep(1);
	}
}
void QuitProcess(const vector<channel> &channels)						//退出进程
{
	//方法1:倒着回收
	int last = channels.size() - 1;
	for (int i = last; i >= 0; i--)
	{
		close(channels[i]._cmdfd);
		waitpid(channels[i]._slaverid, nullptr, 0);
	}
	//方法二:在初始化时关闭子进程多余的管道;
	
	//for (const auto& c : channels)
	//{
	//	close(c._cmdfd);
	//}
	//for (const auto& c : channels) waitpid(c._slaverid, nullptr, 0);   //等待退出
}

int main()
{
	Loadtask(&tasks);							//加载任务参数;
	srand(time(nullptr) ^ getpid() ^ 1023);		//种一个随机数种子
	//再组织
	vector<channel> channels;

	//初始化-------bug?————画图就可以看出来,推荐画一下图!!!答:文件描述符随着创建子进程递增;
	InitProcessPool(&channels);					//初始化
	Debug(channels);							//测试

	//2.开始控制子进程
	ctrlSlaver(channels);						//控制子进程
	
	//3.清理收尾
	QuitProcess(channels);
	return 0;
}

  • 10
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值