<Linux> 实现匿名管道多进程任务派发

实现匿名管道多进程任务派发

mypipe

mypipe.cc

#include <iostream>
#include <string>
#include <unistd.h>
#include <cstring>
#include <cassert>
#include <sys/types.h>
#include <sys/wait.h>
#include <algorithm>
#include "Task.hpp"
#include "Log.hpp"
using namespace std;

#define PROCESS_NUM 10

int waitCommand(int fd, bool &quit)
{
    u_int32_t command = 0;
    ssize_t ret = read(fd, &command, sizeof command);
    Log("子进程读取任务", READ) << endl;
    if (0 == ret)
    {
        quit = true;
        return -1;
    }

    assert(ret == sizeof command);
    return command;
}

int main()
{
    // 装载任务
    load();

    // 父进程保留每个子进程的pid与对应管道文件写端描述符
    vector<pair<pid_t, int>> slots;

    for (size_t i = 0; i < PROCESS_NUM; i++)
    {

        int pipefd[2] = {0};
        int n = pipe(pipefd);

        Log("创建管道文件", CREATE) << endl;

        Log("打开管道文件", OPEN) << endl;

        assert(n != -1);
        // void(n);

        pid_t id = fork();
        assert(id != -1);

        if (0 == id)
        {
            // 子进程
            // 接收任务
            // 保留读,关闭1

            close(pipefd[1]);

            while (true)
            {
                bool quit = false;

                // 等待命令
                // 内部read阻塞等待
                int command = waitCommand(pipefd[0], quit);

                // 执行命令

                if (quit)
                {
                    break;
                }
                if (command > 0 && command < TASK_NUM)
                {

                    // 执行任务
                    callbacks[command]();
                }
                else
                {
                    cout << "非法命令: " << command + 1 << endl;
                }
            }

            exit(0);
            Log("关闭管道文件", CLOSE) << endl;
        }

        // 父进程
        // 保留写,关闭0
        // 保留每个管道对应子进程pid和写端

        close(pipefd[0]);
        slots.push_back(make_pair(id, pipefd[1]));
    }

    // 父进程
    // 分配任务

    srand((unsigned)time(nullptr));

    while (true)
    {

        printf("######################################\n");
        printf("#   1.show task      2.send task     #\n");
        printf("#   3.exit           4.....          #\n");
        printf("######################################\n");

        int command = -1;
        cin >> command;
        if (1 == command)
        {
            // auto it = desc.rbegin();

            // reverse(desc.cbegin(), desc.cend());
            for (auto e : desc)
            {
                cout << e.second << endl;
            }
        }
        else if (2 == command)
        {
            printf("Please chose task: ");

            int task = -1;
            cin >> task;

            // 派发任务给谁?
            int process = rand() % PROCESS_NUM;

            task--;

            write(slots[process].second, &task, sizeof task);

            Log("父进程发送任务", WRITE) << endl;
        }
        else if (3 == command)
        {
            break;
        }
        else
        {
            cout << "非法选项: " << command << endl;
        }

        sleep(2);
    }

    // 关闭fd
    for (auto e : slots)
    {
        close(e.second);
    }

    for (auto e : slots)
    {
        waitpid(e.first, nullptr, 0);
    }

    return 0;
}

Task

Task.hpp

#pragma once
#ifndef _TASK_H_
#define _TASK_H_
#include <unordered_map>
#include <iostream>
#include <functional>
#include <vector>
#include <unistd.h>
using namespace std;

#define TASK_NUM 10

unordered_map<int, string> desc;

typedef function<void()> func;
vector<func> callbacks;
void task_1()
{
    printf("Sub Process [ %d ] 执行任务 1 ......\n", getpid());
}
void task_2()
{
    printf("Sub Process [ %d ] 执行任务 2 ......\n", getpid());
}
void task_3()
{
    printf("Sub Process [ %d ] 执行任务 3 ......\n", getpid());
}
void task_4()
{
    printf("Sub Process [ %d ] 执行任务 4 ......\n", getpid());
}
void task_5()
{
    printf("Sub Process [ %d ] 执行任务 5 ......\n", getpid());
}
void task_6()
{
    printf("Sub Process [ %d ] 执行任务 6 ......\n", getpid());
}
void task_7()
{
    printf("Sub Process [ %d ] 执行任务 7 ......\n", getpid());
}

void task_8()
{
    printf("Sub Process [ %d ] 执行任务 8 ......\n", getpid());
}
void task_9()
{
    printf("Sub Process [ %d ] 执行任务 9 ......\n", getpid());
}
void task_10()
{
    printf("Sub Process [ %d ] 执行任务 10 ......\n", getpid());
}

void load()
{
    desc.insert(make_pair(callbacks.size(), " task_1 "));
    callbacks.push_back(task_1);

    desc.insert(make_pair(callbacks.size(), " task_2 "));
    callbacks.push_back(task_2);

    desc.insert(make_pair(callbacks.size(), " task_3 "));
    callbacks.push_back(task_3);

    desc.insert(make_pair(callbacks.size(), " task_4 "));
    callbacks.push_back(task_4);

    desc.insert(make_pair(callbacks.size(), " task_5 "));
    callbacks.push_back(task_5);

    desc.insert(make_pair(callbacks.size(), " task_6 "));
    callbacks.push_back(task_6);

    desc.insert(make_pair(callbacks.size(), " task_7 "));
    callbacks.push_back(task_7);

    desc.insert(make_pair(callbacks.size(), " task_8 "));
    callbacks.push_back(task_8);

    desc.insert(make_pair(callbacks.size(), " task_9 "));
    callbacks.push_back(task_9);

    desc.insert(make_pair(callbacks.size(), " task_10 "));
    callbacks.push_back(task_10);
}

#endif

Log

#ifndef _LOG_H_
#define _LOG_H_
#pragma once

#include <iostream>
#include <string>

#define CREATE 0
#define OPEN 1
#define WRITE 2
#define READ 3
#define CLOSE 4

std::ostream &Log(std::string message, int mode)
{
    std::cout << "| " << message << " | " << "step " << mode << " | ";
}

#endif

makefile

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据挖掘常见算法(分类算法)

K&#xff0d;近邻算法&#xff08;KNN&#xff09; K-近邻分类法的基本思想&#xff1a;通过计算每个训练数据到待分类元组Zu的距离&#xff0c;取和待分类元组距离最近的K个训练数据&#xff0c;K个数据中哪个类别的训练数据占多数&#xff0c;则待分类元组Zu就属于哪个类别…

win10 修改远程桌面端口,在Win10上修改远程桌面端口的要怎么操作

在Windows 10上修改远程桌面端口是一个涉及系统配置的过程&#xff0c;这通常是为了增强安全性或满足特定网络环境的需要。 一、通过注册表编辑器修改远程桌面端口 1. 打开注册表编辑器&#xff1a; - 按下Win R组合键&#xff0c;打开“运行”对话框。 - 在“运行”对话框…

结构体 (一)

在我们C语言中&#xff0c;为我们提供了不同的内置类型&#xff0c;例如&#xff1a;char 、short 、int 、long 、float 、double 等等&#xff0c;但是呢&#xff0c;仅仅只有这些内置类型是远远不够的&#xff0c;当我们想要描述一名学生&#xff0c;一本书&#xff0c;一件…

Linux:目录和文件管理命令2

目录 一、Linux目录结构&#xff1a; 二、查看文件 2.1、cat 命令——显示并连接&#xff08;Concatenate&#xff09;文件的内容 2.2、more 和 less 命令——分页查看文件内容 2.3、head 和 tail 命令——查看文件开头或末尾的部分内容 三、统计和检索文件内容 3.1、wc…

不知大家信不信,竟有这么巧的事,我领导的老婆,竟然是我老婆的下属,我在想要不要利用下这层关系,改善下领导对我的态度,领导怕老婆

职场如战场&#xff0c;每个人都身不由己。每天上班&#xff0c;除了要面对堆积如山的工作&#xff0c;还要小心应对来自领导的“狂风暴雨”。最近&#xff0c;我无意间发现领导一个秘密&#xff0c;这个秘密让我对职场关系和人性都产生了新的思考。 故事要从那天晚上说起。我…

ARM相关理论知识

一、计算机的组成 1.输入设备&#xff1a;将数据与程序转换成计算机能够识别&#xff0c;存储&#xff0c;运算的形式&#xff0c;输送到计算机中。 2.输出设备&#xff1a;将计算机对程序和数据的运算结果输送到计算机外部设备 3.控制器&#xff1a;由程序技术器&#xff0…

《数字图像处理》实验报告一

一、实验任务与要求 1、用 matlab 编写空间域点处理操作处理给定的几幅图像&#xff0c;要求&#xff1a; 使用 imread 读取当前工作目录下的图像设计点处理操作并用代码实现处理用 imnshow 显示处理后的图像用 imwrite 保存处理后的图像 2、提交内容&#xff1a;m文件 实验…

【ChatBI】超轻量Python库Vanna快速上手,对接oneapi

oneapi 准备 首先确保你有oneapi &#xff0c;然后申请 kimi的api 需要去Moonshot AI - 开放平台 然后添加一个api key 然后打开oneapi的渠道界面&#xff0c;添加kimi。 然后点击 测试&#xff0c; 如果能生成响应时间&#xff0c;就是配置正确。 然后创建令牌 http:…

渗透测试基础(六) MS10-046漏洞攻击

1. 漏洞介绍 1.1 漏洞介绍 Microsoft Windows快捷方式LNK文件自动执行代码漏洞。Windows支持使用快捷方式或LNK文件。LNK文件是指向本地文件的引用,点击LNK文件与点击快捷方式所制定的目标具有相同效果。Windows没有正确的处理LNK文件,特制的LNK文件可能导致Windows自动执行…

微服务(服务治理)

服务远程调用时存在的问题 注册中心原理 服务治理中的三个角色分别是什么&#xff1f; 服务提供者&#xff1a;暴露服务接口&#xff0c;供其它服务调用服务消费者&#xff1a;调用其它服务提供的接口注册中心&#xff1a;记录并监控微服务各实例状态&#xff0c;推送服务变更信…

MIT6.s081 2021 Lab Utilities

Boot xv6 按照示例切换到 util 分支后&#xff0c;看到目录下包含 Makefile 文件&#xff0c;执行 make qemu 即可。 sleep 思路 借助系统调用 sleep 实现一个命令行程序&#xff0c;关键是要找到封装了系统调用的 C 函数的位置&#xff0c;根据提示&#xff1a; … user/u…

物联网系统运维——实验备份与恢复,数据镜像软件DRBD介绍,DRBD的安装和应用,extundelete的安装和应用(重点),环境准备,配置设置

一.数据备份 1.数据备份的重要性 备份是系统中需要考虑的最重要的事项,虽然这在系统的整个规划,开发和测试过程中甚至占不到1%,看似不太重要且默默无闻的工作只有到恢复的时候才能真正体现出其重要性,任何数据的丢失与数据宕机&#xff0c;都是不可以被接收的。 2.数据备份策…

oracle 11g rac安装grid 执行root脚本add vip -n 。。。on node= ... failedFailed 错误处理

问题&#xff1a; CRS-4402: The CSS daemon was started in exclusive mode but found an active CSS daemon on node racdg1-1, number 1, and is terminating An active cluster was found during exclusive startup, restarting to join the cluster PRCN-2050 : The requ…

程序员学长 | 快速学会一个算法,Transformer(下)

本文来源公众号“程序员学长”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;快速学习一个算法&#xff0c;Transformer&#xff08;二&#xff09; 今天我们来继续分享 Transformer 模型的第二部分&#xff0c;解码器部分。 建…

热虹吸管的传热计算

热对称管和热管通过使用中空管内的两相流体&#xff0c;在特定的距离上传输大量的热量。 更广泛使用的热管使用吸芯结构将液体输送回热端&#xff0c;而热虹吸管是一个简单的空心管&#xff0c;使用重力。 由于缺乏吸芯结构&#xff0c;使得热虹吸管比传统的热管便宜得多。 然…

自学指南:必备书籍清单--近100本R语言及生物信息相关书籍

R语言是一种功能丰富的编程语言&#xff0c;数据处理、统计分析是大家所熟知的基本功能。开源免费、活跃的全球社区、灵活可扩展等优点促使R语言飞速发展。目前&#xff0c;CRAN 软件包存储库包含 20446 个可用软件包&#xff0c;涵盖了从生物信息到金融分析等广泛的应用领域。…

vue3.0(十五)内置组件Teleport和Suspense

文章目录 一、Teleport1.基本用法2.禁用Teleport3.多个 Teleport 共享目标4.搭配组件 二、 Suspense1.什么是Suspense2.异步依赖3.加载中状态4.事件5.错误处理6.和其他组件结合注意 一、Teleport <Teleport> 是一个内置组件&#xff0c;它可以将一个组件内部的一部分模板…

第二十八篇——复盘:世界不完美,我们该怎么办?

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么&#xff1f; 四、总结五、升华 一、背景介绍 对于信息传递过程中的相关知识的总结&#xff0c;让我又仿佛回到了每一个…

Python列表比较:判断两个列表是否相等的多种方法

&#x1f4d6; 正文 1 通过排序的方式实现判断 list_a [a, b, c, d] list_b [c, d, a, b]if sorted(list_a) sorted(list_b):print(list_a与list_b的元素相等) else:print(list_a与list_b的元素不相等)通过排序&#xff0c;让两组列表中元素一直后进行判断&#xff0c;得到…

Linux常用基本命令

linux目录 1.查看linux本机ip ip addr 2.新建文件夹 mkdir 文件夹名 3.新建文件 touch 文件名.后缀 4.删除文件 rm 文件名.后缀 5.删除文件 rm -r 文件名 6.不询问直接删除 rm -rf 文件名/文件名/ 7.显示目录下文件&#xff0c;文件夹 作用&#xff1a;显示指定目…