<Linux>进程池 -- 练习

这里实现的进程池:一个父进程对多个子进程进行管道通信,大致如下

一、大致框架

  1. 知道需要创建几个子进程来进行通信

  1. 和这些子进程创建同数量的管道

  1. 实现子进程的数据接收

  1. 实现父进程的数据发送

  1. 结尾处理

注意要实现的是父进程对子进程的通信,发送数据的只有一个进程,而管道是通过fd文件描述符来实现通信的,所以我们需要记录每一个子进程对应的管道,以此来建立父进程对多个子进程之间的联系。(隐藏的意思就是我们只需要对子进程的对应的管道文件发送数据,就可基本实现通信了)

二、demo代码

以下代码,是根据所列的框架所写的,可以参考

int main()
{
    vector<pair<pid_t, int>> slot;
    // 创建子进程
    for (int i = 0; i < PROCESS_NUM; ++i)
    {
        // 创建管道
        int pipefd[2] = {0};
        int n = pipe(pipefd);
        assert(n != -1);
        (void)n;

        pid_t id = fork();
        assert(id >= 0);
        // 子进程
        if (id == 0)
        {
            close(pipefd[1]);
            // 判断数据合法性
            while (true)
            {
                //接收数据
            }

            close(pipefd[0]);
            exit(-1);
        }
        // 父进程
        close(pipefd[0]);
        slot.push_back({id, pipefd[1]});
    }
    // 注意要实现的是一个进程给多个进程发送数据,发送的代码得放在for外面
    // 发送数据
    srand((unsigned long)time);
    while (true)
    {
        //发送数据
    }
    
    //关闭文件
    for (const auto& slots : slot)
    {
        close(slots.second);
    }
    //等待子进程退出
    for (const auto& slots : slot)
    {
        waitpid(slots.first, nullptr, 0);
    }

    return 0;
}

三、具体的接收和发送实现处理

#include <iostream>
#include <sys/types.h>
#include <sys/wait.h>
#include <vector>
#include <string>
#include <unistd.h>
#include <unordered_map>
#include <assert.h>
#include <stdlib.h>
#include "task.hpp"
using namespace std;

#define PROCESS_NUM 5

int waitComment(pid_t waitFd, bool &quit)
{
    uint32_t command = 0;
    ssize_t s = read(waitFd, &command, sizeof(command));//如果读到文件结尾会返回0(写到的文件关闭)
    if (s == 0)
    {
        quit = true;
        return -1;
    }
    assert(s == sizeof(uint32_t));
    return command;
}

void SendData(pid_t who, int fd, int command)
{
    write(fd, &command, sizeof(command));

    cout << "[" << getpid() <<"] send a message:" << endl;
}

int main()
{
    load();
    vector<pair<pid_t, int>> slot;
    // 创建子进程
    for (int i = 0; i < PROCESS_NUM; ++i)
    {
        // 创建管道
        int pipefd[2] = {0};
        int n = pipe(pipefd);
        assert(n != -1);
        (void)n;

        pid_t id = fork();
        assert(id >= 0);
        // 子进程
        if (id == 0)
        {
            close(pipefd[1]);
            // 判断数据合法性
            while (true)
            {
                bool quit = false;
                int comment = waitComment(pipefd[0], quit);
                if (quit == true)
                {
                    break;
                }
                if (comment >= 0 && comment < 5)
                {
                    task[comment]();//只要是if(id == 0)中的代码块,都是由子进程来执行的
                }
                else
                {
                    return -1;
                }
            }

            close(pipefd[0]);
            exit(-1);
        }
        // 父进程
        close(pipefd[0]);
        slot.push_back({id, pipefd[1]});
    }
    // 注意要实现的是一个进程给多个进程发送数据,发送的代码得放在for外面
    // 发送数据
    srand((unsigned long)time);
    while (true)
    {
        int command = rand() % 4;
        int choices = rand() % slot.size();

        //关键点:给不同的子进程发送数据只需要对不同的fd发送数据即可 -- 访问控制
        SendData(slot[choices].first, slot[choices].second, command);

        sleep(1);
    }

    for (const auto& slots : slot)
    {
        close(slots.second);
    }

    for (const auto& slots : slot)
    {
        waitpid(slots.first, nullptr, 0);
    }

    return 0;
}

任务实现文件

#pragma once

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <functional>

using func = std::function<void()>;  //C++11 标准 <返回值(参数类型)>
std::unordered_map<int, std::string> desc; //只是为了方便描述
std::vector<func> task;

void ReadSQL()
{
    std::cout << "[" << getpid() << "]ReadSQL:数据库任务" << std::endl;
}

void Cal()
{
    std::cout << "[" << getpid() << "]Cal:文件加密任务" << std::endl;
}

void Save()
{
    std::cout << "[" << getpid() << "]Save:文件持久化任务" << std::endl;
}

void Exculeurl()
{
    std::cout << "[" << getpid() << "]Exculeurl:url解析任务" << std::endl;
}

void load()
{
    desc.insert({task.size(), "ReadSQL:数据库任务"});
    task.push_back(ReadSQL);

    desc.insert({task.size(), "Cal:文件加密任务"});
    task.push_back(Cal);

    desc.insert({task.size(), "Save:文件持久化任务" });
    task.push_back(Save);

    desc.insert({task.size(), "Exculeurl:url解析任务"});
    task.push_back(Exculeurl);
}

void ShowHandler()
{
    for (auto &e : desc)
    {
        std::cout << e.second << std::endl;
    }
}

size_t HandlerSize()
{
    return desc.size();
}
myProcessPool:myProcessPool.cpp
    g++ -o $@ $^ -std=c++11 
.PHONY:clean
clean:
    rm -f myProcessPool
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绅士·永

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值