Linux——进程通信(二) 匿名管道的应用:进程池

news2024/11/16 16:46:54

前言

之前我们学习了进程通过匿名管道进行通信,实现了两个进程的数据传输。

如果我们管理的是很多个进程,通过管道发送指令,因为如果管道中没有数据,读端必须等待,也就是被管理的进程们都在等待我发送的指令,那么我们可以通过特定的通讯方式,对进程实施控制,也就是让进程根据传输的指令去完成相应的操作。

一、进程池概念

我们知道,系统资源的获取是有成本的,比如我们创建进程,需要花一定的时间去完成,比如现在我们有一些比较重要的任务需要处理,如果等待任务到来,再创建进程去处理任务,时间上会慢一点,如果我们提前将进程创建好,任务到来,我们直接对进程分派任务,这样就能节省时间,这些提前创建好并被管理的进程,有任务来就分派执行,我们可以称之为进程池

打个比方,比如说你喝娃哈哈矿泉水,如果你感觉到口渴了,才去外面超市买娃哈哈矿泉水,这样成本是不是比较高,有点浪费时间,但是如果你提前在家里面放上一箱娃哈哈矿泉水,渴了就喝,顺手就拿的事情,效率就提高了,这也相当于把矿泉水进行池化了。

二、进程池实现

主要思路是先创建进程和信道,再发布任务,最后等待关闭父进程的写进程,让子进程read读到0,就退出子进程。最后父进程进行资源回收。

具体可以看代码注释,这里就不多BB了

ProcessPool.cpp

#include <iostream>
#include <unistd.h>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>
#include "Task.hpp"
using namespace std;

#define NUM 5

class channel
{
public:
    channel(string name, int fd, pid_t pid)
        : _name(name), _fd(fd), _pid(pid)
    {}

public:
    string _name;
    int _fd;
    pid_t _pid;
};

void Work()
{
    while (true)
    {
        int code = 0;
        ssize_t n = read(0, &code, sizeof(code));
        if (n == sizeof(code))
        {
            if (!init.Check(code))
            {
                cout << "任务码不合法,执行失败" << endl;
                continue;
            }
            init.RunTask(code);
        }
        else if (n == 0)
            break;
    }
}

void CreatProcess(vector<channel> &v)
{
    vector<int> vfd; // 存放父进程的写信道的fd
    for (int i = 0; i < NUM; i++)
    {
        // 创建管道
        int pipefd[2];
        int n = pipe(pipefd);
        assert(n == 0);

        // 创建进程
        pid_t id = fork();
        if (id < 0)
        {
            perror("fork");
            exit(1);
        }
        // 构建信道
        else if (id == 0)
        {
            // 子进程
            vfd.push_back(pipefd[1]);
            for (auto &fd : vfd) // 关闭子进程继承的写信道
            {
                close(fd);
            }
            dup2(pipefd[0], 0);
            Work();
            exit(0);
        }
        // 父进程
        close(pipefd[0]);
        v.push_back(channel(to_string(i + 1) + "号信道", pipefd[1], id));
    }
}

void PrintChannel(const vector<channel> &v)
{
    for (auto &c : v)
    {
        cout << c._name << "," << c._fd << "," << c._pid << endl;
    }
}

void SendTask(const vector<channel> &v, bool flag, int num = 1)
{
    int pos = 0;
    while (true)
    {
        int task = init.SelectTask(); // 选择任务
        pos %= v.size();              // 选择信道轮流执行任务
        channel c = v[pos++];

        cout<<"发送信息"<<init.ToDesc(task)<<"给"<<c._name<<",pid是"<<c._pid<<endl;

        write(c._fd, &task, sizeof(task)); // 发送任务

        if (!flag)
        {
            if (--num <= 0)
                break;
        }
        sleep(1);
    }
    sleep(1);
    cout << "发送任务完成" << endl;
}

void WaitPorcess(vector<channel> v)
{
    for (auto &c : v)
    {
        close(c._fd);
        pid_t rid = waitpid(c._fd, nullptr, 0);
        cout<<"等待子进程"<<c._pid<<"成功"<<endl;
    }
}

int main()
{
    vector<channel> channels;
    // 创建进程和信道
    CreatProcess(channels);
    // PrintChannel(channels);  //打印测试

    // 发送任务
    const bool always_loop = true;
    SendTask(channels, !always_loop, 10);

    // 进程等待回收
    WaitPorcess(channels);
    return 0;
}

Task.hpp

#pragma once

#include <iostream>
#include <functional>
#include <vector>
#include <ctime>

using namespace std;

typedef function<void()> task_t;

void Download()
{
    cout << "我正在下载,"
         << "pid:" << getpid() << endl;
}

void Print()
{
    cout << "我正在打印,"
         << "pid:" << getpid() << endl;
}

void PlayVideo()
{
    cout << "我正在播放,"
         << "pid:" << getpid() << endl;
}

class Init
{
public:
    Init()
    {
        tasks.push_back(Download);
        tasks.push_back(Print);
        tasks.push_back(PlayVideo);
        srand(time(nullptr));
    }

    void RunTask(int code)
    {
        tasks[code]();
    }

    string ToDesc(int code)
    {
        switch (code)
        {
        case 0:
            return "Download";
        case 1:
            return "Print";
        case 2:
            return "PlayVideo";
        default:
            return "Unkonw";
        }
    }

    bool Check(int code)
    {
        return code >= 0 && code < tasks.size();
    }

    int SelectTask()
    {
        return rand() % tasks.size();
    }

public:
    vector<task_t> tasks;
    // 任务码
    const int download_code = 0;
    const int print_code = 1;
    const int PlayVideo_code = 2;
};

Init init;

 运行结果如下。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1526694.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DevExpress WinForms crack,DevExpress WinForms组件套件和库

DevExpress WinForms crack,DevExpress WinForms组件套件和库 Reporting & Analytics - Reports, Pivot Tables, PDF Viewer. The DevExpress WinForms Subscription includes royalty-free user interface components for next-gen decision support systems. Whether you…

SegFormer 项目排坑记录

SegFormer 项目排坑记录 任务记录创建conda环境 准备数据库和预训练参数程序配置修改测试可视化训练 任务 需要复现SegFormer分割项目&#xff0c;似乎还有点麻烦&#xff0c;参考这几个进行复现&#xff0c;记录下过程&#xff1a; SegFormer mmsegmentation CSDN博客 知乎博…

保姆级教学!微信小程序设计全攻略!

微信小程序开启了互联网软件的新使用模式。在各种微信小程序争相抢占流量的同时&#xff0c;如何设计微信小程序&#xff1f;让用户感到舒适是设计师在产品设计初期应该考虑的问题。那么如何做好微信小程序的设计呢&#xff1f;即时设计总结了以下设计指南&#xff0c;希望对准…

车企都卷入鸿蒙开发的行了!难怪岗位需求量涨这么快!!!

近日华为鸿蒙 OS 官微宣布&#xff0c;首批汽车行业伙伴广汽传祺、岚图汽车、零跑汽车、凯翼汽车官宣加入鸿蒙生态。 这四家车企加入&#xff0c;会不会影响着其他车企想哪些手机APP厂商那种陆续的跟上呢&#xff1f; 其实在此前国内新能源扛把子比亚迪早已与华为达成了合作&a…

纳米阱可提高未来光学设备的光强度

一种配置光捕获器件的方法有望通过放大光和提高发光纳米材料的发射效率来获得更好的光学纳米器件&#xff0c;而无需复杂的技术升级。 强光束对于从医学到电子产品的无数应用至关重要&#xff0c;但使用日常光源生产它们具有挑战性。然而&#xff0c;它们可以由激光产生。激光…

校园暴力谁之过?如何正确引导孩子行为?

近日&#xff0c;关于河北邯郸校园霸凌事件持续发酵&#xff0c;很多媒体包括央视都是密切关注此事的发展动向&#xff0c;很多媒体人也在持续报道后续事态。那么对于14岁的的少年来说&#xff0c;花样年华的年纪&#xff0c;究竟为什么会犯下如此大的罪行&#xff1f;孩子为什…

电脑msvcp140_1.dll丢失的解决方法,总结5种可靠的方法

在日常使用电脑的过程中&#xff0c;我们可能会遇到一些错误提示&#xff0c;其中之一就是“msvcp1401.dll丢失”。这个DLL文件是Microsoft Visual C Redistributable Package的一部分&#xff0c;对于许多基于Windows的应用程序来说至关重要。这个错误通常会导致某些应用程序无…

系统渐渐沦为“屎山”,这就是真相!

分享是最有效的学习方式。 博客&#xff1a;https://blog.ktdaddy.com/ 背景 小猫维护现有的系统也有一段时间了&#xff0c;踩坑也不少&#xff0c;事故不少。感兴趣的小伙伴可以了解一下&#xff0c;往期的小猫踩坑记合集。 这天&#xff0c;小猫找到了商城系统的第一任开发…

【数据结构与算法】:非递归实现快速排序、归并排序

&#x1f525;个人主页&#xff1a; Quitecoder &#x1f525;专栏&#xff1a;数据结构与算法 上篇文章我们详细讲解了递归版本的快速排序&#xff0c;本篇我们来探究非递归实现快速排序和归并排序 目录 1.非递归实现快速排序1.1 提取单趟排序1.2 用栈实现的具体思路1.3 代码…

掘根宝典之C++RTTI和类型转换运算符

什么是RTTI RTTI是运行阶段类型识别的简称。 哪些是RTTI? C有3个支持RTTI的元素。 1.dynamic_cast运算符将使用一个指向基类的指针来生成一个指向派生类的指针&#xff0c;否则该运算符返回0——空指针。 2.typeid运算符返回一个指出对象类型的信息 3.type_info结构存储…

【鸿蒙HarmonyOS开发笔记】如何使用图片插帧将低像素图片清晰放大

开发UI时&#xff0c;当我们的原图分辨率较低并且需要放大显示时&#xff0c;图片会模糊并出现锯齿。如下图所示 这时可以使用interpolation()方法对图片进行插值&#xff0c;使图片显示得更清晰。该方法的参数为ImageInterpolation枚举类型&#xff0c;可选的值有: ImageInte…

通过点击按钮实现查看全屏和退出全屏的效果

动态效果如图&#xff1a; 可以通过点击按钮&#xff0c;或者esc键实现全屏和退出全屏的效果 实现代码&#xff1a; <template><div class"hello"><el-button click"fullScreen()" v-if"!isFullscreen">查看全屏</el-butt…

centos创建并运行一个redis容器 并支持数据持久化

步骤 : 创建redis容器命令 docker run --name mr -p 6379:6379 -d redis redis-server --appendonly yes 进入容器 : docker exec -it mr bash 链接redis : redis-cli 查看数据 : keys * 存入一个数据 : set num 666 获取数据 : get num 退出客户端 : exit 再退…

猫头虎分享已解决Bug || TypeError: Cannot interpret ‘float‘ value as integer.

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

luceda ipkiss教程 62:等长波导布线(二)

教程 27介绍了两段波导等长布线的例子&#xff0c;下面同样是通过控制偏移量实现三段波导的等长布线&#xff1a; 所有代码如下&#xff1a; from si_fab import all as pdk from ipkiss3 import all as i3class demo(i3.Circuit):mmi i3.ChildCellProperty(doc"mmi in…

数据导入--Insert into

Insert Into是我们在MySQL中常用的导入方式&#xff0c;StarRocks同样也支持使用Insert into的方式进行数据导入&#xff0c;并且每次insert into操作都是一次完整的导入事务。 在StarRocks中&#xff0c;Insert的语法和MySQL等数据库的语法类似&#xff0c;具体可以参考官网文…

苹果谷歌,要联手反攻了

一则消息&#xff0c;让苹果、谷歌的夜盘股价一度分别暴拉1.5、3.5%&#xff0c;谷歌盘前甚至飙升超过5.5%&#xff0c;引发市场一阵轰动。 据知情人士透露&#xff0c;苹果公司正在谈判将谷歌的Gemini人工智能引擎植入iPhone&#xff0c;希望获得Gemini的授权&#xff0c;为今…

【办公类-22-11】周计划系列(5-3)“周计划-03 周计划内容循环修改“ (2024年调整版本)

背景需求&#xff1a; 前文从原来的“新模版”文件夹里提取了周计划主要内容和教案内容。 【办公类-22-10】周计划系列&#xff08;5-2&#xff09;“周计划-02源文件docx读取5天“ &#xff08;2024年调整版本&#xff09;-CSDN博客文章浏览阅读1.1k次&#xff0c;点赞29次&…

全基因集GSEA富集分析

原文链接&#xff1a;一文完成全基因集GSEA富集分析 本期内容 写在前面 我们前面分享过一文掌握单基因GSEA富集分析的教程&#xff0c;主要使用单基因的角度进行GSEA富集分析。 我们社群的同学咨询&#xff0c;全基因集的GSEA如何分析呢&#xff1f;&#xff1f;其实&#x…

利用自定义 URI Scheme 在 Android 应用中实现安全加密解密功能

在现代移动应用开发中&#xff0c;安全性和用户体验是至关重要的考虑因素。在 Android 平台上&#xff0c;开发人员可以利用自定义 URI Scheme 和 JavaScript 加密解密技术来实现更安全的数据传输和处理。本文将介绍如何在 Android 应用中注册自定义 URI Scheme&#xff0c;并结…