【进程间通信】管道应用场景---简易进程池

news2025/1/10 22:52:01

#include<iostream>
#include<vector>
#include<string>
#include<cstring>
#include<cstdlib>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/wait.h>


//把5个子进程要管理起来,要先描述再组织
const int processnum=5;
//先描述
class channel
{
public:
    channel(pid_t slaverpid,int cmdfd,std::string slavername)
    :_slaverpid(slaverpid),_slavername(slavername),_cmdfd(cmdfd)
    {}
public:
    pid_t _slaverpid;//子进程pid
    int _cmdfd;//发送任务的文件描述符
    std::string _slavername;//子进程的名字,方便打印日志
};


void  Slaver()
{
    while(true)
    {
        int cmdnode=0;
        int n=read(0,&cmdnode,sizeof(int));
        if(n==sizeof(int))
        {
            std::cout<<std::endl;
            std::cout <<"slaver say@ get a command: "<< " cmdcode: " << cmdnode << std::endl;
            //执行任务列表
            switch(cmdnode)
            {
                case 1:
                {
                    std::cout<<"刷新野怪"<<std::endl;
                    break;
                }
                case 2:
                {
                    std::cout<<"购买装备"<<std::endl;
                    break;
                }
                case 3:
                {
                    std::cout<<"释放技能"<<std::endl;
                    break;
                }               
                case 4:
                {
                    std::cout<<"查看战绩"<<std::endl;
                    break;
                }
            }

        }
        if(n==0) break;
    }
}
void Initprocesspool(std::vector<channel>& channels)
{
    std::vector<int> oldwfd;//用来存储旧的写端fd, 确保每一个子进程都只有一个写端
    for(int i=0;i<processnum;i++)
    {
        int pipefd[2]={0};
        int n=pipe(pipefd);
        if(n<0) return ;


        pid_t id=fork();
        if(id==0) //child
        {
            for(auto& fd:oldwfd) close(fd);//关闭从父进程继承下来的写端
            close(pipefd[1]);

            dup2(pipefd[0],0);//把标准输入重定向到读端文件,简化代码,可以不这么写
            Slaver();
            close(pipefd[0]);
            exit(0);
        }

        close(pipefd[0]);

        //添加channel字段
        std:: string name="process-"+std::to_string(i);
        channels.push_back(channel(id,pipefd[1],name));
        oldwfd.push_back(pipefd[1]);
        
        
    }

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

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 Ctrlprocess(std::vector<channel> channels)
{
    
    while(true)
    {
        int select=0;
        menu();
        std::cout<<"please select@";
        std::cin>>select;
        if(select<1||select>4) break ;

        //选择进程,随机选择
        int processpos=rand()%channels.size();

        std::cout<<"father say:"<<"select:"<<select<<"  can todo "<<
        channels[processpos]._slaverpid<<"slavername:"<<channels[processpos]._slavername<<std::endl;

        //发放任务
        write(channels[processpos]._cmdfd,&select,sizeof(select));
        sleep(1);

    }
}

void Quitprocess(const std::vector<channel>& channels)
{
    for(const auto& process:channels)
    {
        close(process._cmdfd);
        waitpid(process._slaverpid,nullptr,0);
    }
}

int main()
{
    srand(time(nullptr));
    std::vector<channel> channels;
    //1.初始化进程池
    Initprocesspool(channels);
    Debug(channels);

    //2.控制子进程
    Ctrlprocess(channels);

    //3.清理收尾

    Quitprocess(channels);

    return 0;


}


 

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

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

相关文章

SPI驱动学习二(驱动框架)

目录 一、回顾平台总线设备驱动模型二、SPI设备驱动1. 数据结构1.1 SPI控制器数据结构1.2 SPI设备数据结构1.3 SPI设备驱动 2. SPI驱动框架2.1 SPI控制器驱动程序2.2 SPI设备驱动程序 三、SPI设备树处理过程1. SPI Master2. SPI Device3. 设备树示例4. 设备树实例4.1 使用GPIO模…

leetcode 899. Orderly Queue

原题链接 You are given a string s and an integer k. You can choose one of the first k letters of s and append it at the end of the string. Return the lexicographically smallest string you could have after applying the mentioned step any number of moves. …

Java集合类之Collection

文章目录 1 准备部分1.1 数据结构1.1.1 数组1.1.2 链表 1.2 集合是什么 2 Collection2.1 特点2.2 常用API2.3 遍历Collection的方法2.3.1 toArray方法2.2.2 iterator方法2.3.3 foreach2.3.4 总结 3 List 接口3.1 内容提要3.2 特点3.3 List的API3.3.1 listIterator方法3.3.4 sub…

【RabbitMQ应用篇】常见应用问题

1. 消息幂等性保障 1.1 幂等性介绍 幂等性&#xff1a;这个概念在数学和计算机领域中相当常见&#xff0c;表示可以被应用多次但是不会改变初始应用结果的性质。 应用程序的幂等性&#xff1a;指的是在一个应用系统中&#xff0c;重复调用多次请求&#xff08;相同参数&#…

【Python机器学习】神经网络的组成

目录 感知机 数字感知机 认识偏置 Python版神经元 “课堂时间” 有趣的逻辑学习问题 下一步 代价函数 反向传播算法 求导 误差曲面 不同类型的误差曲面 多种梯度下降算法 Keras&#xff1a;用Python实现神经网络 展望 归一化&#xff1a;格式化输入 神经网络对…

C语言 面向对象编程

注意事项 在使用面向对象编程的时候&#xff0c;我们得问自己&#xff1a;任务中有什么对象&#xff0c;对象应该怎么使用 项目中文档体系 我们可以规划一下任务得文档&#xff0c;可以为每一个对象的类单独编写源码&#xff0c;并发布对应的头文件作为接口&#xff0c;主控…

Android CCodec Codec2 (六)C2InterfaceHelper

通过前面几篇文章的学习&#xff0c;我们知道了Codec2参数结构&#xff0c;以及如何定义一个Codec2参数。接下来的几篇文章我们将简单了解上层是如何请求组件支持的参数、如何配置参数&#xff0c;以及参数是如何反射给上层的。本篇文章我们将了解接口参数实例化。 1、C2Interf…

Linux零基础到精通(二)-vmware虚拟机使用教程及Centos7操作系统安装

目录 前言Linux 操作系统运用领域vmware虚拟机安装与使用电脑硬件环境要求vmware虚拟机软件安装创建一个虚拟机配置vmware的虚拟化网络 通过vmware虚拟机安装操作系统下载Centos7系统镜像安装Centos7操作系统配置网络和主机名称信息配置系统分区软件包选择设置用户密码进入Cent…

入门Java编程的知识点—>静态方法(day11)

重点掌握final关键字特点&#xff1f;final的语法使用?重点掌握静态变量是什么&#xff1f;静态变量的语法与使用?了解方法区内存图执行过程?重点掌握静态方法是什么&#xff1f;静态方法的语法特点与使用?重点掌握常量语法如何定义与使用? final(最终) final可以用于修…

IT运维问题深度剖析与一体化解决方案探索

在当今信息化高速发展的时代&#xff0c;IT运维作为保障企业业务连续性和稳定性的关键环节&#xff0c;其重要性日益凸显。然而&#xff0c;随着企业规模的扩大和业务的复杂化&#xff0c;IT运维面临着诸多挑战和问题。本文旨在深度剖析当前IT运维中的紧迫性问题与需求&#xf…

C++学习, 指针的指针

指针的指针&#xff1a; 是一种间接寻址的形式&#xff0c;指针的指针就是将指针的地址存放在另一个指针里面。一般&#xff0c;指针包含一个变量的地址&#xff0c;当定义一个指向指针的指针时&#xff0c;第一个指针包含了第二个指针的地址&#xff0c;第二个指针指向实际值…

day35-测试之性能测试JMeter的测试报告、并发数计算和性能监控

目录 一、JMeter的测试报告 1.1.聚合报告 1.2.html报告 二、JMeter的并发数计算 2.1.性能测试时的TPS&#xff0c;大都是根据用户真实的业务数据&#xff08;运营数据&#xff09;来计算的 2.2.运营数据 2.3.普通计算方法 2.4.二八原则计算方法 2.5.计算稳定性测试并发量 2.6…

Java性能优化传奇之旅--Java万亿级性能优化之Java 性能优化传奇:热门技术点亮高效之路

💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的博客,正是这样一个温暖美好的所在。在这里,你们不仅能够收获既富有趣味又极为实…

MOELoRA —— 多任务医学应用中的参数高效微调方法

人工智能咨询培训老师叶梓 转载标明出处 在医疗场景中&#xff0c;LLMs可以应用于多种不同的任务&#xff0c;如医生推荐、诊断预测、药物推荐、医学实体识别、临床报告生成等。这些任务的输入和输出差异很大&#xff0c;给统一模型的微调带来了挑战。而且LLMs的参数众多&…

Nginx 维护与应用:最佳实践

文章目录 引言安装与基础维护macOS 上安装 NginxUbuntu 上安装 NginxCentOS 上安装 NginxWindows 上安装 Nginx查看 Nginx 运行状态与日志信息&#xff08;Linux&#xff09;版本升级与配置备份&#xff08;Linux&#xff09; Nginx 应用场景Web 服务器反向代理动静分离负载均衡…

“线程池中线程异常后:销毁还是复用?”

目录 一、验证execute提交线程池中 测试 结论 二、验证submit提交线程池中 测试 结论 三、源码解析 查看submit方法的执行逻辑 查看execute方法的执行逻辑 为什么submit方法&#xff0c;没有创建新的线程&#xff0c;而是继续复用原线程&#xff1f; 四、总结 需要说…

Android AOSP定制默认输入法为讯飞输入法

Android AOSP定制默认输入法为讯飞输入法 前言&#xff1a; ​ 最近在公司的项目中发现默认的输入法非常不好用&#xff0c;而且默认输入法中英文切换非常麻烦&#xff0c;被用户吐槽定制的AOSP镜像体验不好&#xff0c;于是查找资料&#xff0c;研究了一番&#xff0c;尝试了…

【C++】日期类函数(时间计数器)从无到有实现

欢迎来到HarperLee的学习笔记&#xff01; 博主主页传送门&#xff1a;HarperLee的博客主页 个人语录&#xff1a;他强任他强&#xff0c;清风拂山岗&#xff01; 一、前期准备 1.1 检查构造的日期是否合法 bool Date::CheckDate() {if (_month < 1 || _month > 12|| _d…

vercel免费在线部署TodoList网页应用

参考&#xff1a; TodoList网页应用&#xff1a;https://blog.csdn.net/weixin_42357472/article/details/140909096 1、项目首先上传github 直接vscode自带的上传项目&#xff0c;commit后在创建项目上传即可 2、vercel部署项目 1&#xff09;先注册 2&#xff09;impor…

基于PHP评论区的存储型XSS漏洞

评论区的XSS漏洞是指攻击者在评论区输入恶意脚本&#xff0c;当其他用户浏览该页面时&#xff0c;这些恶意脚本会被执行&#xff0c;从而造成安全威胁。这种漏洞通常出现在网站没有对用户输入进行充分过滤和转义的情况下&#xff0c;为存储型XSS。存储型XSS攻击是指攻击者在目标…