Linux之进程间通信(二)---模拟进程池

进程池

创建多个子进程

只有一个父进程一个子进程

外层套循环创建多个进程

父进程还要对channle进行先描述在组织

对管道进行描述->class Channel


大纲

1.创建多个子进程

2.对子进程和管道进行管理

3.释放资源


阶段检测是否创建子进程成功和文件描述符


接下来对现有函数进行封装--利用c++类

cpp 复制代码
class ProcessPool
{
public:
    // a. 创建多个进程,创建多个管道
    int CreateProcessPool()
    {
        for (int i = 0; i < 5; i++)
        {

            int pipefd[2] = {0};
            int n = pipe(pipefd);
            if (n < 0)
            {
                cerr << "pipe error" << endl;
                return pipeerror;
            }
            pid_t id = fork();
            if (id < 0)
            {
                cerr << "fork error" << endl;
                return forkerror;
            }
            else if (id == 0)
            {
                // 子进程
                close(pipefd[1]); // 子进程关掉写,进行读
                DoTask(pipefd[0]);
                exit(OK);
            }
            else
            {
                // 父进程
                close(pipefd[0]); // 父进程写
                // pipefd[1]循环一下就没有了,要储存
                Channel ch(pipefd[1], id); // 将子进程和要写的管道文件进行记录
                channels.push_back(ch);
                cout << " 创建子进程成功,pid:" << id << endl;
            }
        }
        return OK;
    }

    void DebugPrint()
    {
        for(auto &ch : channels)
        {
            ch.Print();
        }
    }

private:
    // 未来维护和组织所有的channel
    vector<Channel> channels;
};

将创建多个子进程,和打印,文件描述符,创建子进程是否成功都封装到ProcessPool这个类里面,然后将vector<Channel> channels 变成该类的成员变量,main函数的内容变得十分简洁

实现完成不同任务的需求

约定统一四字节进行读写

任务我们想要不要让他很重复,这个时候要用到函数指针,然后回调的操作来实现

  • function<void(int)>可调用对象包装器
    • void:函数返回值为 void
    • (int):这个可调用对象接收 1 个 int 类型参数

task_t就是别名,代表:所有可以接收 int 参数、返回 void 的可调用类型

可以包装:普通函数、函数指针、lambda 表达式、仿函数对象。

cpp 复制代码
using task_t=function<void(int)>;

task_t 是类型别名,代表:一个可调用对象,接收 1 个 int 参数,返回 void


cpp 复制代码
void CreateProcessPool(task_t cb)
  • cb:callback 回调,类型是task_t
  • 意思:函数CreateProcessPool接收一个可调用对象 进来,不在本函数内部执行,交给子进程去调用

cpp 复制代码
//子进程分支
close(pipefd[1]);
cb(pipefd[0]);   // 执行回调!
exit(OK);

子进程拿到管道读端pipefd[0],把文件描述符当做实参传给回调,执行用户传入的函数。


cpp 复制代码
pool.Init(DoTask);

DoTask函数传进去。DoTask签名:void DoTask(int fd),正好匹配 void(int)

整体流程:main 把 DoTask 作为回调传给 Init → Init 传给 CreateProcessPool → fork 出子进程 → 子进程调用 cb(pipefd[0]),等价执行DoTask(pipefd[0])


对子进程和管道进行管理

那么要如何选择一个进程呢???

比较好的是将任务平均分配到子进程

1.轮询

2.随机

3.权重

接下来我们采用轮询的方式来分配任务
选择任务

制作任务清单

任务表实现的底层

typedef 干了什么

typedef void(*mytask_list)();

  • void (*)():这是函数指针类型,代表:保存一个函数地址,该函数没有参数,返回值 void。
  • typedef:给这个复杂类型起一个简短名字:mytask_list
cpp 复制代码
// 普通:int a;  a是int类型变量
// 现在:mytask_list  fp;  fp就是一个函数指针变量,可以存函数地址
mytask_list fp = SyncDick;
fp(); //等价 SyncDick();

mytask_list mytask[4];

  • mytask[4]:这是函数指针数组,数组里面每一格,都能存放一个函数的地址。

  • {SyncDick, Download, PrintLog, UpdateStatus}:把 4 个全局函数的地址,依次填进数组 0、1、2、3 下标位置。

    数组下标 存储的函数地址 调用写法
    0 SyncDick mytask[0](); →执行 SyncDick ()
    1 Download mytask[1](); →执行 Download ()
    2 PrintLog mytask[2](); →执行 PrintLog ()
    3 UpdateStatus mytask[3](); →执行 UpdateStatus ()

种下随机数种子^pid,让取出来的数更加随机

验证任务分配是否随机

发送任务给进程

processpool

Channel补充写和管道名的成员函数

子进程完成发送过来的任务

释放资源

processpool创建成员函数Quit用来释放资源

要将管道关闭

然后将子进程进行回收

问题一

如果父进程关闭,但是子进程还没有跑完会有影响吗

是没有的,子进程只有将管道内容全部读完才会结束

问题二

将Quit这样可以吗

发现卡住了

那么这是为什么呢???

实际上是因为管道文件没有被关干净

子进程是以父进程为模板创建的,很多的内核数据结构的信息都是和父进程一样的

也就是说,越到后面创建的子进程对于前面父进程创造的管道文件都拥有写的权限

将父进程对于管道文件的写权限关闭,其管道文件对应的子进程并不能接受到管道以全部关闭,然后再退出,因为这其中后面创建的子进程对于改管道文件依然可以写入

那么应该要如何解决这个问题呢???

解决方案:

1.从最后一个创建的子进程开始关闭管道文件

2.实现真正w:r=1:1

让之后创建的子进程关闭之前的管道文件

相关推荐
薛定谔的悦3 小时前
储能 EMS 的功率策略:从一块电表到一次逆流的 200 毫秒
大数据·linux·能源·储能·bms
2601_962218475 小时前
万象生鲜系统区块链溯源技术帮助生鲜企业搭建食品安全数字化体系
大数据·运维·微服务·云原生·架构
智塑未来5 小时前
中小公司在线文档选型:从协作入口到安全边界
运维·安全
新时代牛马6 小时前
Linux 内核入门地图:架构、源码目录与五大子系统
linux·运维·架构
智购科技无人售货机厂家6 小时前
2026自动售货机制冷系统维护指南:从散热器清洁到压缩机换油的工程实践~YH
运维·redis·物联网·缓存·架构
剑客的茶馆6 小时前
开发者,运维怎样转行FDE?
运维·ai·开发·fde
Julien20046 小时前
控制 SELinux 文件上下文
linux·运维·服务器
sulikey6 小时前
Linux Core Dump 完全指南:从原理到实战的崩溃调试手册。什么是core dump?程序报错core dumped怎么办?
linux·服务器·操作系统·调试·coredump
Lifangyun_WD6 小时前
第一次租 GPU 服务器怎么开始?镜像、SSH、数据存储和停机前要做什么
服务器·云计算·gpu算力·gpu算力租赁
众壹新能源科技6 小时前
功率预测误差考核怎么降?从气象源到上报口径的排查清单
运维·人工智能·自动化