Linux-使用管道实现简易版本的进程池

2023-12-13 03:48:56

目录

一.程序概念图

二.makefile的编写????????

三.Task.hpp编写

四.ProcessPool.cc编写


一.程序概念图

????????

?

二.makefile的编写????????

ProcessPool:ProcessPool.cc
	g++ -o $@ $^ -std=c++11
.PHONY:clean
clean:
	rm -rf ProcessPool

三.Task.hpp编写

#pragma once

#include <vector>
#include <iostream>


typedef void (*task_t) ();

void task1()
{
    std::cout << "lol 刷新日志" << std::endl;
}
void task2()
{
    std::cout << "lol 更新野区,刷新出来野怪" << std::endl;
}
void task3()
{
    std::cout << "lol 检测软件是否更新,如果需要,就提示用户" << std::endl;
}
void task4()
{
    std::cout << "lol 用户释放技能,更新用的血量和蓝量" << std::endl;
}

void LoadTask(std::vector<task_t> *tasks)
{
    tasks->push_back(task1);
    tasks->push_back(task2);
    tasks->push_back(task3);
    tasks->push_back(task4);
}

四.ProcessPool.cc编写

#include <ctime>
#include <string>
#include <vector>
#include "Task.hpp"
#include <cassert>
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/fcntl.h>


using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::to_string;

class channel
{
public:
    channel(int cmdfd, pid_t slaverid, std::string processname)
        :_cmdfd(cmdfd),_slaverid(slaverid),_processname(processname)
        {}

public:
    int _cmdfd;                                                                        // 发送任务的文件描述符
    pid_t _slaverid;                                                                   // 子进程的PID
    string _processname;                                                               // 子进程的名字 -- 方便我们打印日志
};

void Menu();                                                                           //菜单
void Slaver();
void Debug(const vector<channel> &channels);
void Mester(const vector<channel>& channels);
void InitProcessPool(vector<channel> *channels);                                       //创建子进程
void QuitProcess(const vector<channel>& channels);

const int processnum = 10;
vector<task_t> tasks;

int main(void)
{
    //初始化随机数生成器
    srand((unsigned int)time(nullptr));

    //构建一个顺序表,用来管理创建好的管道文件
    vector<channel> channels;

    //创建任务表
    LoadTask(&tasks);

    //创建子进程
    InitProcessPool(&channels);
    Debug(channels);

    //控制子进程
    Mester(channels);

    //清理子进程
    QuitProcess(channels);
    return 0;
}

void InitProcessPool(vector<channel> *channels)
{
    int i_i = 0;
    for( i_i = 0; i_i < processnum; i_i++)
    {
        //申请管道文件
        int pipefd[2];
        int n = pipe(pipefd);                                                           //0表示管道文件申请成功,-1表示失败同时更新错误码
        assert(!n);
        (void)n;                                                                        //确保这个变量被使用以免程序在编译阶段报错

        pid_t id = fork();
        if(id < 0 )
        {
            return;
        }
        else if(id == 0)
        {
            close(pipefd[1]);
            dup2(pipefd[0], 0);
            close(pipefd[0]);

            Slaver();

            exit(0);
        }
        else if(id  > 0)
        {
            close(pipefd[0]);

            string str = "processname" + to_string(i_i);

            channels->push_back(channel(pipefd[1], id, str));
        }
    }

}

void Debug(const vector<channel> &channels)
{
    // test
    for(const auto &c :channels)
    {
        std::cout << c._cmdfd << " " << c._slaverid << " " << c._processname << std::endl;
    }
}

void Slaver()
{
    while(true)
    {
        int cmdcode = 0;

        int n = 0;
        n = read(0, &cmdcode, sizeof(int));
        if(n < 0)
        {
            cout << "读取文件失败!" << endl;
        }

        if(n == sizeof(int))
        {
            cout <<"slaver say@ get a command: "<< getpid() << " : cmdcode: " <<  cmdcode << std::endl;
            //执行相应的任务
            if(cmdcode >= 0 && cmdcode < tasks.size())
            {
                tasks[cmdcode]();
            }
        }

        if(n == 0)
        {
            break;
        }
        //sleep(1);
    }
}

void Mester(const vector<channel>& channels)
{
    int cnt = 1;
    while(true)
    {
        //选择任务
        Menu();
        
        cout << "请选择您想要执行的操作:";
        // int which = 0;
        // cin >> which;

        //int cmdcode = which - 1;
        //模拟实现用户的输入
        int cmdcode = 0;
        cmdcode = ((rand() % 4) + 1);
        if(cnt > 4)
        {
            cmdcode = 0;
        }
        cout << cmdcode << endl;

        if(cmdcode == 0)
        {
            break;
        }
        cnt++;

        //选择进程
        int processnumber = 0;
        processnumber = (rand() % processnum);

        std::cout << "father say: " << " cmdcode: " <<
            cmdcode << " already sendto " << channels[processnumber]._slaverid << " process name: " 
                << channels[processnumber]._processname << std::endl;

        write(channels[processnumber]._cmdfd, &cmdcode, sizeof(cmdcode));


        sleep(10);
        
    }
}

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 QuitProcess(const vector<channel>& channels)
{
    for(auto e : channels)
    {
        close(e._cmdfd);
    }

    for(auto e : channels)
    {
        waitpid(e._slaverid, nullptr, 0);
    }
}

文章来源:https://blog.csdn.net/weixin_52159554/article/details/134806628
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。