Linux--进程间的通信--进程池

这篇具有很好参考价值的文章主要介绍了Linux--进程间的通信--进程池。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

进程间的通信–匿名管道

进程池的概念

进程池是一种将多个进程组织起来以执行特定任务的机制它由多个预先创建好的资源进程和一个管理进程组成。这些资源进程被管理进程负责分配和调度,用于处理任务

当有新的任务提交时,管理进程会从进程池中取出一个资源进程,将任务分发给它来处理。任务完成后,资源进程并不会被关闭,而是被放回进程池中,等待处理其他的任务。这样可以避免频繁地创建和销毁进程,节省了时间和资源。

进程池的主要优势包括减少操作系统的调度难度,节省创建和销毁进程的时间,并在一定程度上实现并发效果。通过有效地管理资源进程和任务分配,进程池可以提高系统的整体性能和效率。

下面我们来模拟实现进程池,来加深对进程池的理解。

模拟场景

通过主程序的创建,当做管理进程;然后再创建几个子进程作为资源进程,在主函数模拟n个任务来临时,轮盘调用可用的资源进程。

代码

task.hpp:这是一个任务头文件,包含了有关任务的模拟,任务的处理,任务的派发的任务有关函数。

#pragma once

#include<iostream>
#include<unistd.h>
using namespace std;

typedef void(*work_t)(int);
typedef void(*task_t)(int,pid_t);

void PrintLog(int fd,pid_t pid)
{
    cout << "sub process: " << pid << ", fd: " << fd<< ", task is : printf log task" << endl;
}
void ReloadConf(int fd,pid_t pid)
{
    cout << "sub process: " << pid << ", fd: " << fd<< ", task is : reload conf task" << endl;
}
void ConnectMysql(int fd,pid_t pid)
{
    cout << "sub process: "<< pid <<", fd: "<<fd<< ",task is: connact mysql task"<<endl;
}

task_t task[3]={PrintLog,ReloadConf,ConnectMysql};

uint32_t NextTask()
{
    return rand()%3;
}
void worker(int fd)
{
    while(true)
    {
        uint32_t commond_code=0;
        ssize_t n=read(0,&commond_code,sizeof(commond_code));
        if(n==sizeof(commond_code))
        {
            if(commond_code >=3)continue;
            task[commond_code](fd,getpid());
        }
        else if(n==0)
        {
            cout<<"get sub_process:"<<getpid()<<" quit now:"<<endl;
            break;
        }
        cout<<"I am worker : "<<getpid()<<endl;
        sleep(1);
    }
}

processpool.cpp: 这里面包含了进程池(创建资源进程、发送任务码、回收资源进程、资源进程的管理)、进程池的控制(进程通道的选择、任务的选择、任务的选择)、进程间的通道(包含父进程的文件标识符、子进程的进程ID、通道的名称)以及主函数;

#include<iostream>
#include<string>
#include<cstdlib>
#include<unistd.h>
#include<vector>
#include<ctime>
#include<sys/wait.h>
#include"task.hpp"

using namespace std;


enum
{
    UsageError=1,
    ArgError,
    PipeError
};

void Usage(const std::string &proc)
{
    cout<<"Usage: "<<proc<<"subprocess-num"<< endl;
}

class channel
{
public:
    channel(int wfd,pid_t sub_id,const std::string& name)
    :_wfd(wfd),
    _sub_process_id(sub_id),
    _name(name)
    {}

    void PrintDebug()
    {
        cout<<"_wfd:"<<_wfd<<" ";
        cout<<"_sub_process_id:"<<_sub_process_id<<" ";
        cout<<"_name:"<<_name<<" ";
        cout<<endl;
    }
    string name(){return _name;}
    int wfd(){ return _wfd;}
    pid_t pid() { return _sub_process_id;}
    void Close() { close(_wfd); }
    ~channel()
    {}
private:
    int _wfd;
    pid_t _sub_process_id;
    string _name;
};

class ProcessPool
{
public:
    //构造函数初始化
    ProcessPool(int sub_process_num)
    :_sub_process_num(sub_process_num)
    {}

    int CreateProcess(work_t work)
    {
        vector<int> fds;
        for(int number=0;number<_sub_process_num;number++)
        {
            int pipefd[2]{0};
            int n=pipe(pipefd);
            if(n<0)
            {
                return PipeError;
            }
            pid_t id=fork();
            if(id==0)
            {
                if(!fds.empty())
                {
                    cout<<"close w fd:";
                    for(auto fd:fds)
                    {
                        close(fd);
                        cout<<fd<<" ";
                    }
                    cout<<endl;
                }
                //child
                close(pipefd[1]);
                //执行任务  
                dup2(pipefd[0],0);
                work(pipefd[0]);
                exit(0);
            }
            string cname="channel-"+ to_string(number);

            close(pipefd[0]);
            //保存对应的子进程通道信息
            _channels.push_back(channel(pipefd[1],id,cname));
            //将父进程的fd进行保存
            fds.push_back(pipefd[1]);
        }

        return 0;
    }
    int NextChannel()
    {
        static int next =0;
        int c=next;
        next++;
        next%=_channels.size();
        return c;
    }
    void SendTaskCode(int index,uint32_t code)
    {
        cout<<"send code: "<<code<<" to "<<_channels[index].name()<<" sub process id: "<<_channels[index].pid()<<endl;
        write(_channels[index].wfd(),&code,sizeof(code));
    }
    void KillAll()
    {
        for(auto& C : _channels)
        {
            C.Close();
            pid_t pid=C.pid();//获取对应子进程id
            //waitpid()成功返回子进程的ID,失败返回-1;
            pid_t rid=waitpid(pid,nullptr,0);
            if(rid==pid)
            {
                cout<<"wait sub_process: "<<pid<<"sucess..."<<endl;
            }
            cout<<C.name()<<" close done"<<" sub process quit now"<<C.pid()<<endl;
        }
    }
    void Debug()
    {
        for(auto& channel: _channels)
        {
            channel.PrintDebug();
        }
    }
    ~ProcessPool()
    {}
private:
    int _sub_process_num;
    vector<channel> _channels;
};

void CtrlProcessPool(ProcessPool* processpool_ptr,int cnt)
{
    while(cnt)
    {
        //选择一个进程和通道
        int channel=processpool_ptr->NextChannel();

        //选择一个任务
        uint32_t code=NextTask();

        //发送任务
        processpool_ptr->SendTaskCode(channel,code);
        
        sleep(1);
        cnt--;
    }
}

//,/processpool 5
int main(int argc,char* argv[])
{
    if(argc!=2)
    {
       Usage(argv[0]);
        return UsageError;
    }
    int sub_process_num=std::stoi(argv[1]);
    if(sub_process_num <=0) return ArgError;
    
    srand((uint64_t)time(nullptr));
    //创建通信和子进程
    ProcessPool *processpool_ptr=new ProcessPool(sub_process_num);
    processpool_ptr->CreateProcess(worker);
    processpool_ptr->Debug();

    //控制子进程
    CtrlProcessPool(processpool_ptr,sub_process_num);
    cout<<"task run done"<<endl;
    
    //sleep(100);

    //回收子进程
    processpool_ptr->KillAll();

    delete processpool_ptr;
    return 0;
}



讲解

Linux--进程间的通信--进程池,Linux,linux,运维,服务器
Linux--进程间的通信--进程池,Linux,linux,运维,服务器
Linux--进程间的通信--进程池,Linux,linux,运维,服务器
Linux--进程间的通信--进程池,Linux,linux,运维,服务器
Linux--进程间的通信--进程池,Linux,linux,运维,服务器
Linux--进程间的通信--进程池,Linux,linux,运维,服务器
Linux--进程间的通信--进程池,Linux,linux,运维,服务器
Linux--进程间的通信--进程池,Linux,linux,运维,服务器
Linux--进程间的通信--进程池,Linux,linux,运维,服务器
Linux--进程间的通信--进程池,Linux,linux,运维,服务器
Linux--进程间的通信--进程池,Linux,linux,运维,服务器
Linux--进程间的通信--进程池,Linux,linux,运维,服务器
Linux--进程间的通信--进程池,Linux,linux,运维,服务器
Linux--进程间的通信--进程池,Linux,linux,运维,服务器
Linux--进程间的通信--进程池,Linux,linux,运维,服务器
Linux--进程间的通信--进程池,Linux,linux,运维,服务器
Linux--进程间的通信--进程池,Linux,linux,运维,服务器

Linux--进程间的通信--进程池,Linux,linux,运维,服务器

如果匿名管道有多个写端,情况会比较复杂。匿名管道的特性决定了它只能实现一对一的通信,即一个写端对应一个读端。如果多个写端同时写入数据,可能会导致以下问题:

  • 1.写入顺序混乱:由于多个写端并发写入,写入的顺序可能会混乱,导致数据的顺序不可预测。
  • 2.写入内容被覆盖:多个写端同时写入时,如果没有采取合适的同步机制,可能会发生数据覆盖的情况,即后面的写入会覆盖前面的写入结果。
  • 3.数据丢失:如果某个写端写入速度快于其他写端,读端可能无法及时消费所有写入的数据,导致数据丢失。

为了避免这些问题,通常需要在使用匿名管道时进行适当的同步操作,例如使用互斥锁、条件变量等机制来保证多个写端之间的互斥访问和顺序执行。

Linux--进程间的通信--进程池,Linux,linux,运维,服务器
Linux--进程间的通信--进程池,Linux,linux,运维,服务器
Linux--进程间的通信--进程池,Linux,linux,运维,服务器文章来源地址https://www.toymoban.com/news/detail-857827.html

到了这里,关于Linux--进程间的通信--进程池的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux下的系统编程——进程间的通信(九)

    前言:  前面我们已经对进程已经有了一个简单的了解与认识,那么进程间的通信是什么样的呢,什么是父子进程,什么是兄弟进程,没有血缘关系间的进程是如何实现进程通信的,下面让我们一起学习一下什么是进程间的通信吧。 目录 一、进程间通信常用方式 IPC方式:

    2024年02月09日
    浏览(32)
  • 运维 | 查看 Linux 服务器 IP 地址

    大多数在操作 Linux 系统时,我们经常需要知道服务器的 IP 比便于后续的一系列操作,这时候有快速查看主机 IP 的命令行操作,能够有效的帮助我们 本章节主要记录一些常用查看服务器 IP 的命令,希望对大家有所帮助。 查看 Linux 服务器的 IP 地址的命令大体上有以下几种。

    2024年04月27日
    浏览(76)
  • 【运维】Linux 跨服务器复制文件文件夹

    如果是云服务 建议用内网ip scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的。可能会稍微影响一下速度。当你服务器硬盘变为只读 read only system时,用scp可以帮你把文件移出来

    2024年02月08日
    浏览(66)
  • linux并发服务器 —— 多进程并发(四)

    程序是包含一系列信息的文件,描述了如何在运行时创建一个进程; 进程是正在运行的程序的实例,可以用一个程序来创建多个进程; 用户内存空间包含程序代码以及代码所使用的变量,内核数据结构用于维护进程状态信息; 进程控制块(PCB):维护进程相关的信息,tas

    2024年02月11日
    浏览(51)
  • 【Linux 服务器运维】定时任务 crontab 详解 | 文末送书

    本文思维导图概述的主要内容: 1.1 什么是 crontab Crontab 是一个在 Unix 和 Linux 操作系统上 用于定时执行任务 的工具。它允许用户创建和管理计划任务,以便在特定的时间间隔或时间点自动运行命令或脚本。Crontab 是 cron table 的缩写, cron 指的是 Unix 系统中的一个后台进程,它

    2024年02月08日
    浏览(85)
  • Linux服务器上查询进程 ps aux

    在Linux服务器上查询进程,有以下几种方法: 使用ps命令。这个命令用于报告当前系统的进程状态。可以用以下方式使用ps命令来查看进程信息: ps aux:显示系统中所有进程的信息。 ps -e:显示所有进程的信息。 ps -f:显示进程的所有信息。 ps -l:以长格式显示进程信息。

    2024年02月05日
    浏览(59)
  • 【Linux运维】shell脚本检查服务器内存和CPU利用率

    在管理服务器时候写了一个 shell脚本,在服务上实现每天凌晨3点查系统的指定文件夹下的容量大小,如果超过10G就要删除3天前的内容,还要时刻查询内存和cpu利用率,如果超过80%就要提示用户出现过载 将以上代码保存为一个.sh文件,然后通过crontab在每天凌晨3点运行即可:

    2024年02月09日
    浏览(64)
  • Linux服务器中查看进程的四种方法

    1. 使用 ps aux 命令来查看,能以简单列表的形式显示出进程信息 ps aux 用于报告当前系统的进程状态。可以搭配kill指令随时中断、删除不必要的程序. ps 命令是最基本同时也是非常强大的进程查看命令,使用该命令可以确定有哪些进程正在运行和运行的状态、进程是否结束、进

    2024年02月02日
    浏览(40)
  • Linux网络编程:多进程 多线程_并发服务器

    文章目录: 一:wrap常用函数封装 wrap.h  wrap.c server.c封装实现 client.c封装实现 二:多进程process并发服务器 server.c服务器 实现思路 代码逻辑  client.c客户端 三:多线程thread并发服务器 server.c服务器 实现思路 代码逻辑  client.c客户端 ​​​​   read 函数的返回值 wrap.h  wrap

    2024年02月12日
    浏览(54)
  • Linux服务器常见运维性能测试(1)综合跑分unixbench、superbench

    最近需要测试一批服务器的相关硬件性能,以及在常规环境下的硬件运行稳定情况,需要持续拷机测试稳定性。所以找了一些测试用例。本次测试包括在服务器的高低温下性能记录及压力测试,高低电压下性能记录及压力测试,常规环境下CPU满载稳定运行的功率记录。 这个系

    2024年02月04日
    浏览(74)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包