首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【Linux】匿名管道实现简单进程池

【Linux】匿名管道实现简单进程池

作者头像
用户10923276
发布于 2024-04-15 00:09:48
发布于 2024-04-15 00:09:48
20800
代码可运行
举报
运行总次数:0
代码可运行

一、匿名管道通信的四种情况和五种特性

1.1、四种情况

  1. 管道内部没有数据且子进程不关闭自己的写端文件fd,读端(父进程)就要阻塞等待,直到管道里有数据。
  2. 管道内部被写满了且父进程(读端)不关闭自己的读端fd,写端(子进程)写满以后就要阻塞等待。
  3. 对于写端而言,如果写端不写了且关闭了写端fd,读端就会将管道中的数据读完,最后会读到返回值为0,表示读结束,类似于读到了文件的结尾。
  4. 读端关闭了,操作系统就会发送信号直接杀死进行写入的进程,因为没有读端写入也就没有了意义。

1.2、五种特性

  1. 管道自带同步机制,参照上面四种情况中的1,2,3。
  2. 具有血缘关系的进程进行通信,常见于父子。
  3. 管道是面向字节流的。
  4. 父子进程退出,管道自动释放,因为内存中的文件的生命周期是随进程的。 
  5. 管道只能进行单向通信。

二、匿名管道实现简单的进程池

        这个进程池可以分配我们想要的进程的个数,用命令行的方式来控制进程的个数,任务由我们自己定好,每次随机选择一个任务指派给一个进程去完成,进程的选派采用轮询的方式按顺序指派,这其中还有一些实现的细节,会在代码中以注释的方式给出。

头文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <vector>
#include <sys/wait.h>
#include <vector>
using namespace std;

typedef void (*work_t)(int pipefd);//pipefd为写端文件描述符
typedef void (*task_t)(int pipefd, pid_t fd);//fd为子进程pid

//三个任务
void PrintLog(int pipefd, pid_t fd)
{
    cout <<"pipefd:" << pipefd <<" fd:" << fd <<  " task:printf log task" << endl;
}

void ReloadConf(int pipefd, pid_t fd)
{
     cout <<"pipefd:" << pipefd <<" fd:" << fd <<  " task:Reload Conf" << endl;
}

void ConnectMysql(int pipefd, pid_t fd)
{
     cout <<"pipefd:" << pipefd <<" fd:" << fd <<  " task:Connect Mysql" << endl;
}

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

//随机在三个任务中选择一个
uint32_t nextTask()
{
    return rand() % 3;
}


void worker(int pipefd)
{
    while(true)
    {
        uint32_t code = 0;
        //子进程会阻塞在此读,读到零就证明写端已经关闭了
        int n = read(0, &code, sizeof(code));

        if(n == sizeof(code))
        {
            if(code >= 3) continue;
            task[code](pipefd, getpid());
            sleep(1);
        }
        else if(n == 0)
        {
            cout << "child process quit now!" << endl;
            break;
        }
    }
}

源文件 

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include "processpool.hpp"

enum
{
    UsageError = 1,
    ArgError,
    PipeError
};

void Usage(char *proc)
{
    cout << "Usage:" << proc << " num" << endl;
}

class Channel
{
private:
    //管道保存写端文件描述符,管道名和子进程pid。
    int _wfd;
    string _name;
    pid_t _processid;

public:
    Channel(int wfd, string name, pid_t id)
        : _wfd(wfd), _name(name), _processid(id)
    {
    }

    void print()
    {
        cout << "_wfd:" << _wfd << " _name:" << _name << " _processid:" << _processid << endl;
    }

    const string name() const
    {
        return _name;
    }

    const int wfd() const
    {
        return _wfd;
    }

    const pid_t processid() const
    {
        return _processid;
    }

    void Close()
    {
        close(_wfd);
    }

    ~Channel()
    {
    }
};

//进程池
class processPool
{
private:
    int _sum_child_process;//进程池中进程的个数
    vector<Channel> _channelVect;

public:
    processPool(int sum_child_process)
        : _sum_child_process(sum_child_process)
    {
    }

    // 创建信道和子进程
    int CreateProcess(work_t work)//任务以函数指针的方式传入
    {
        vector<int> fds;
        for (int i = 0; i < _sum_child_process; i++)
        {
            //创建匿名管道
            int pipefd[2];
            int n = pipe(pipefd);
            if (n == -1)
                return PipeError;
            pid_t id = fork();
            if (id == 0)
            {
                //关闭多余的写端描述符,因为父进程在创建子进程的同时会将父进程的文件描述符表也给子进程拷贝一份,
                //这样子进程的文件描述符表就会保存了之前的子进程的写端文件描述符,必须要把之前的子进程的写端文件描述符关闭,
                //否则子进程在退出的时候会出异常
                if (!fds.empty())
                {
                    for (auto e : fds)
                        close(e);
                }
                close(pipefd[1]);
                dup2(pipefd[0], 0);//输入重定向
                work(pipefd[0]);
                exit(0);
            }
            string name = "Channel" + to_string(i);
            close(pipefd[0]);
            _channelVect.push_back(Channel(pipefd[1], name, id));
            fds.push_back(pipefd[1]);
        }
        return 0;
    }
    //发送某个任务给某个管道
    void SendTaskCode(const Channel *channel, uint32_t code)
    {
        cout << "send code: " << code << " to " << channel->name() << " sub prorcess id: " << channel->processid() << endl;
        write(channel->wfd(), &code, sizeof(code));
    }

    // 控制子进程
    void CtrlProcessPool(processPool *processPoolPtr, int cnt)//cnt表示任务的个数
    {
        while (cnt)
        {
            // 1、选择一个进程和信道
            const Channel *cur = processPoolPtr->nextChannel();
            cout << cur->name() << endl;

            // 2、选择一个任务
            uint32_t n = nextTask();

            // 派送任务
            processPoolPtr->SendTaskCode(cur, n);
            sleep(1);
            cnt--;
        }
    }

    //按顺序选择一个管道
    const Channel *nextChannel()
    {
        static int n = 0;
        n %= _sum_child_process;
        return &_channelVect[n++];
    }

    void Print()
    {
        for (auto &channel : _channelVect)
        {
            channel.print();
        }
    }

    // 退出所有子进程
    void killAll()
    {
        for (auto &Channel : _channelVect)
        {
            Channel.Close();
            pid_t rid = Channel.processid();
            pid_t quitid = waitpid(rid, nullptr, 0);
            if (rid == quitid)
                cout << rid << " quit succeed!" << endl;
        }
    }   
    ~processPool()
    {
    }
};

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        return ArgError;
    }

    // 创建信道和子进程
    int sum_child_process = stoi(argv[1]);
    processPool *processPoolPtr = new processPool(sum_child_process);
    // vector<Channel> channelVect;
    processPoolPtr->CreateProcess(worker);

    srand(time(nullptr));

    // 控制子进程
    int cnt = 10;//10个任务
    processPoolPtr->CtrlProcessPool(processPoolPtr, cnt);

    // 回收子进程
    processPoolPtr->killAll();
    //processPoolPtr->Wait();

    delete processPoolPtr;
    return 0;
}

makefile

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
myprocesspool:processpool.cc
	g++ -o $@ $^
.PHONY:clean
clean:
	rm -f myprocesspool
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-04-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
开源搜索引擎排名第一,Elasticearch是如何做到的?
随着移动互联网、物联网、云计算等信息技术蓬勃发展,数据量呈爆炸式增长。如今我们可以轻易得从海量数据里找到想要的信息,其中离不开搜索引擎技术的帮助。特别是其中的索引、检索和排序机制,我们无需深入了解背后复杂的信息检索原理,即可实现基本的全文检索功能。数据量达到十亿,百亿规模仍然可以秒级返回检索结果。对于系统容灾、数据安全性、可扩展性、可维护性等我们关注的实际问题,在开源搜索引擎领域排名第一的Elasticsearch里均能得到有效解决。
腾讯云大数据
2021/01/07
1.4K0
开源搜索引擎排名第一,Elasticearch是如何做到的?
10分钟快速入门海量数据搜索分析引擎 Elasticsearch
随着移动互联网、物联网、云计算等信息技术蓬勃发展,数据量呈爆炸式增长。如今我们可以轻易得从海量数据里找到想要的信息,其中离不开搜索引擎技术的帮助。特别是其中的索引、检索和排序机制,我们无需深入了解背后复杂的信息检索原理,即可实现基本的全文检索功能。数据量达到十亿,百亿规模仍然可以秒级返回检索结果。对于系统容灾、数据安全性、可扩展性、可维护性等我们关注的实际问题,在开源搜索引擎领域排名第一的Elasticsearch里均能得到有效解决。
石松
2020/08/23
2.1K0
10分钟快速入门海量数据搜索分析引擎 Elasticsearch
全文搜索引擎Elasticsearch,这篇文章给讲透了
由于近期在公司内部做了一次分享,所以本篇主要是基于之前的博文的一个总结,希望通过这篇文章能让读者大致了解Elasticsearch是做什么的以及它的使用和基本原理。
大数据技术架构
2019/08/16
10K3
全文搜索引擎Elasticsearch,这篇文章给讲透了
深入搜索引擎之 Elasticsearch 必知必会(一):开发视角
两句话了解它是什么 1. 搜索引擎。提供了数据存储、数据处理、数据查询、聚合统计的能力。 2. 创始人说:“不要求你必须是一个数据科学家才能把它用好” 前言 Elasticsearch 是一个很有意思的产品,不同岗位的人,对它的关注维度区别比较大 主要可以分三个层面 开发 基本功能 底层工作原理 数据建模最佳实践 运维 容量规划 性能优化 问题诊断 滚动升级 搜索结果优化 查全率、查准率等指标 搜索与如何解决搜索的相似性问题 具体场景下的调优 对比传统数据库的区别主要在于 传统关系型数据库 事务性 Joi
QQ音乐技术团队
2022/01/06
1.4K0
「Elasticsearch + Lucene」搜索引擎的架构、倒排索引和搜索过程
许多年前,一个名叫Shay Banon的开发者,带着新婚妻子去伦敦生活,在得知妻子想从事厨师工作后,准备利用自己所学为妻子开发一个食谱搜索引擎,他开始使用Lucene的一个早期版本。但是尝试之后,他发现直接使用Lucene给没有任何开发经验的妻子而言是非常困难的,因此Shay 开始对Lucene进行封装。不久他发布了他的第一个基于Lucene的用java编写的开源项目 Compass。后来Shay找到了一份跟高性能和分布式有关的工作,然后发现这份工作对实时、分布式搜索引擎的需求尤为突出,于是他决定重写Compass,把它变为一个独立的服务并取名Elasticsearch,再到后来Elasticsearch发布了第一个公开版本,从此以后,Elasticsearch已经成为了 Github 上最活跃的开源项目之一。据说,Shay的妻子还在等着她的食谱搜索引擎,而他已经在大公司忙的“一发不可收拾”…
一个会写诗的程序员
2020/09/10
1.7K0
「Elasticsearch + Lucene」搜索引擎的架构、倒排索引和搜索过程
如何优雅的规划elasticsearch的索引(index)
index(索引)是elasticsearch中最高层次的数据单元,类似于关系型数据库中的表。每个索引都具有自己唯一的名称与_id。并且可以进行不同的参数配置与mapping映射。以适应不同的业务场景。索引中的最小单位是文档。每一条文档(doc)都是一个json格式的数据对象。包含了实际的具体数据以及该数据所对应的元数据。文档可以是结构化,半结构化或非结构化的数据。索引在elasticsearch中被用于存储,检索鱼分析数据。通过对索引进行搜索与聚合操作可以快速的找到相关的文档,并进行后续的数据分析并在Kibana中进行可视化。
空洞的盒子
2023/11/08
2K4
何时使用Elasticsearch而不是MySql
MySQL 和 Elasticsearch 是两种不同的数据管理系统,它们各有优劣,适用于不同的场景。本文将从以下几个方面对它们进行比较和分析:
wayn
2023/08/09
1.1K0
何时使用Elasticsearch而不是MySql
一文帮你彻底搞明白ElasticSearch
如:当系统数据量上了10亿、100亿条的时候,我们在做系统架构的时候通常会从以下角度去考虑问题:
lyb-geek
2019/10/10
1.3K0
一文帮你彻底搞明白ElasticSearch
深度解析ElasticSearch:构建高效搜索与分析的基石
在数据爆炸的时代,如何快速、准确地从海量数据中检索出有价值的信息成为了企业面临的重要挑战。ElasticSearch,作为一款基于Lucene的开源分布式搜索和分析引擎,凭借其强大的实时搜索、分析和扩展能力,成为了众多企业的首选。本文将深入解析ElasticSearch的核心原理、架构设计及优化实践,帮助读者全面理解这一强大的工具。
小马哥学JAVA
2024/09/19
5020
全文搜索引擎选ElasticSearch还是Solr?
最近项目组安排了一个任务,项目中用到了基于 Solr 的全文搜索,但是该 Solr 搜索云项目不稳定,经常查询不出来数据,需要手动全量同步。
Rookie
2019/04/25
1.2K0
全文搜索引擎选ElasticSearch还是Solr?
腾讯万亿级 Elasticsearch 技术解密
Elasticsearch(ES)作为开源首选的分布式搜索分析引擎,通过一套系统轻松满足用户的日志实时分析、全文检索、结构化数据分析等多种需求,大幅降低大数据时代挖掘数据价值的成本。腾讯在公司内部丰富的场景中大规模使用 ES,同时联合 Elastic 公司在腾讯云上提供内核增强版的 ES 云服务,大规模、丰富多样的的使用场景推动着腾讯对原生 ES 进行持续的高可用、高性能、低成本优化。今天给大家分享在 Elastic 中国开发者大会上的演讲内容:腾讯万亿级 Elasticsearch 技术解密。
用户7069579
2020/03/13
1.4K0
ElasticSearch深度解析入门篇:高效搜索解决方案的介绍与实战案例讲解,带你避坑
如:当系统数据量上了 10 亿、100 亿条的时候,我们在做系统架构的时候通常会从以下角度去考虑问题: 1)用什么数据库好?(mysql、oracle、mongodb、hbase…) 2)如何解决单点故障;(lvs、F5、A10、Zookeep、MQ) 3)如何保证数据安全性;(热备、冷备、异地多活) 4)如何解决检索难题;(数据库代理中间件:mysql-proxy、Cobar、MaxScale 等;) 5)如何解决统计分析问题;(离线、近实时)
汀丶人工智能
2023/10/31
7020
ElasticSearch深度解析入门篇:高效搜索解决方案的介绍与实战案例讲解,带你避坑
Elasticsearch学习,请先看这一篇!
题记 Elasticsearch研究有一段时间了,现特将Elasticsearch相关核心知识、原理从初学者认知、学习的角度,从以下9个方面进行详细梳理。欢迎讨论…… 0. 带着问题上路—ES是如何产生的? ---- (1)思考:大规模数据如何检索? 如:当系统数据量上了10亿、100亿条的时候,我们在做系统架构的时候通常会从以下角度去考虑问题: 1)用什么数据库好?(MySQL、sybase、Oracle、达梦、神通、MongoDB、Hbase…) 2)如何解决单点故障;(lvs、F5、A10、Zoo
铭毅天下
2018/03/20
5.2K0
Elasticsearch学习,请先看这一篇!
腾讯Elasticsearch海量规模背后的内核优化剖析
Elasticsearch 在腾讯内部广泛应用于日志实时分析、结构化数据分析、全文检索等场景,目前单集群规模达到千级节点、万亿级吞吐,同时腾讯联合 Elastic 公司在腾讯云上提供了内核增强版 ES 云服务。海量规模、丰富的应用场景推动着腾讯对原生 ES 进行持续的高可用、高性能、低成本等全方位优化。本次分享主要剖析腾讯对 Elasticsearch 海量规模下的内核优化与实践,希望能和广大 ES 爱好者共同探讨推动 ES 技术的发展。
腾讯云大数据
2021/01/07
7430
腾讯Elasticsearch海量规模背后的内核优化剖析
如何合理规划Elasticsearch的索引|得物技术
随着ES在业务场景中的使用逐渐增多,平台对ES集群的稳定性、管理、运维的压力逐渐增大,通过日常的运维情况来看,发现用户对ES的了解熟悉程度参差不齐,经常性的遇到索引创建不规范,或者参考别人索引的创建脚本进行创建索引,对索引没有一个比较清晰的认知,对索引结构的规划也寥寥无几,为此,平台使用了一些列手段来帮助用户提前合理规划模板,比如索引、模板的创建接入飞书审批流,平台侧会逐一结合业务场景和ES集群情况详细沟通确定索引或者模板结构;又比如ES内核增加业务不停服的动态扩分片能力,旨在进行不合理索引的治理提升ES集群稳定性(索引一旦创建分片是不能修改的),我们内部改动ES源码实现了不停服动态扩分片。
用户10346649
2025/04/15
2220
如何合理规划Elasticsearch的索引|得物技术
【ES三周年】通过Elasticsearch来搭建搜索引擎
Elasticsearch也简称为ES,其实就是一个实时搜索和分析引擎,它可以近乎实时的数据存储、检索与分析数据。ES是一个基于开源的可高扩展的分布式全文搜索引擎,它自身可扩展性非常好,可以扩展到能够处理PB级别的数据。ES是基于Lucene作为核心来实现所有搜索和索引的功能的,之所以这样做就是为了通过简单的RESTful API来隐藏Lucene的复杂性,进而让全文搜索成为一个简单的操作。
三掌柜
2023/02/15
1.6K8
【ES三周年】通过Elasticsearch来搭建搜索引擎
腾讯Elasticsearch海量规模背后的内核优化剖析
Elasticsearch 在腾讯内部广泛应用于日志实时分析、结构化数据分析、全文检索等场景,目前单集群规模达到千级节点、万亿级吞吐,同时腾讯联合 Elastic 公司在腾讯云上提供了内核增强版 ES 云服务。海量规模、丰富的应用场景推动着腾讯对原生 ES 进行持续的高可用、高性能、低成本等全方位优化。本次分享主要剖析腾讯对 Elasticsearch 海量规模下的内核优化与实践,希望能和广大 ES 爱好者共同探讨推动 ES 技术的发展。
黄华
2020/05/09
2.7K2
腾讯Elasticsearch海量规模背后的内核优化剖析
【搜索引擎:Elasticsearch】从0了解ES,整合springboot,京东搜索实战
SQL : like %冷环渊% 但是数据量一旦变大了,就会变慢,这个时候用索引, 也是只能快一些
冷环渊
2022/04/17
1.2K0
【搜索引擎:Elasticsearch】从0了解ES,整合springboot,京东搜索实战
你想要拥有自己的搜索引擎吗?
在现代开发的应用系统中,无论是常规的web应用,还是近几年兴起的app应用,或者是风头正热的大数据应用,都离不开搜索这一功能,搜索也是在应用系统中使用频率最高的一个功能,比如普通的商城系统中的商品搜索或者一些资源的站内搜索等。
yuanyi928
2020/09/14
6350
看完这篇还不会Elasticsearch,我跪搓衣板!
本文转载自:https://www.cnblogs.com/jajian/p/11223992.html
天涯泪小武
2019/08/15
8090
看完这篇还不会Elasticsearch,我跪搓衣板!
推荐阅读
相关推荐
开源搜索引擎排名第一,Elasticearch是如何做到的?
更多 >
目录
  • 一、匿名管道通信的四种情况和五种特性
    • 1.1、四种情况
    • 1.2、五种特性
  • 二、匿名管道实现简单的进程池
    • 头文件
    • 源文件 
    • makefile
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档