进程池搭建

news2024/5/19 6:32:26

进程池流程

  • 父进程流程
  1. 父进程创建N个子进程,让每个子进程挂起,等待进行文件传输
  2. 父进程创建监听套接字,等待客户端新连接到来
  3. 父进程创建epoll实例,监听响应的文件描述符
  4. 父进程接收客户端的连接请求,accept之后得到peerfd,之后传递给一个空闲子进程(进程间传递文件描述符)
  5. 如果管道可读,表示子进程已执行完任务,将子进程标记为空闲状态
  • 子进程流程:
  1. 子进程recvFd一直阻塞在管道上,如果管道中有数据到来,子进程从recvmsg中返回,可以给客户端传输文件
  2. 传输文件结束后,关闭连接,通知父进程
  3. 等待下一次任务

搭建进程池框架

//子进程信息
typedef struct{
    pid_t pid;
    int fd;
    short busy;
}process_date

父进程需要管理每一个子进程,根据父子进程各自流程,搭建进程池框架

父进程流程

#include"processpool.h"
#include<func.h>

int main(int argc, char argv[]){
    //IP,port,pnum
    ARGC_CHEAK(argc, 4);
    int pnum = atoi(argv[3]);
    //0.构建子进程的结构体信息
    pProcess_data_t pProcessData = calloc(pnum, sizeof(Process_data));
    //1.父进程创建N个子进程
    makeChild(pProcessData, pnum);

    //2.创建监听套接字,开启服务器监听操作
    //创建TCP监听套接字
    int listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listenfd < 0)
    {
        perror("listen");
        exit(EXIT_FAILURE);
    }
    printf("listenfd : %d",listenfd);

    int on;
    int ret = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
    if (ret < 0)
    {
        perror("setsockopt");
        exit(EXIT_FAILURE);
    }
    //绑定网络地址
    struct sockaddr_in saddr;
    //初始化
    memset(&saddr, 0, sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[2]));

    //指定IP地址
    saddr.sin_addr.s_addr = inet_addr(argv[1]);

    ret = bind(listenfd, (const struct sockaddr*)&saddr, sizeof(saddr));
    if (ret < 0)
    {
        perror("bind");
        close(listenfd);
        exit(EXIT_FAILURE);
    }
    //进行监听
    ret = listen(listenfd, pnum);
    if (ret < 0)
    {
        perror("listen");
        close(listenfd);
        exit(EXIT_FAILURE);
    }
    printf("server start listening");

    //3.创建epoll实例
    int epfd = epoll_create1(0);
    if (epfd < 0)
    {
        perror("epoll creat");
        exit(EXIT_FAILURE);
    }
    
    //4.对文件描述符进行监听
    //4.1对listenfd进行监听
    struct epoll_event evt;
    memset(&evt, 0, sizeof(evt));
    evt.data.fd = listenfd;
    evt.events = EPOLLIN;
    int ret = epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &evt);
    if (ret < 0)
    {
        perror("epoll_ctl");
        exit(EXIT_FAILURE);
    }
    
    for (int i = 0; i < pnum; i++)//对管道进行监听
    {
        struct epoll_event evt;
        memset(&evt, 0, sizeof(evt));
        evt.data.fd = pProcessData[i].fd;
        evt.events = EPOLLIN;
        int ret = epoll_ctl(epfd, EPOLL_CTL_ADD, pProcessData[i].fd, &evt);
        if (ret < 0)
        {
            perror("epoll_ctl : listen process");
            exit(EXIT_FAILURE);
        }
    }
    struct epoll_event* pEvtArr = (struct epoll_event*)calloc(pnum + 1, sizeof(struct epoll_event));
    while (1)
    {
        int nready = epoll_wait(epfd, &evt, pnum + 1, -1);
        if (nready < 0)
        {
           perror("epollwait");
            exit(EXIT_FAILURE);
        }
        for (size_t i = 0; i < nready; i++)
        {
            int fd = pEvtArr[i].data.fd;
            if (fd == listenfd)//新连接交给子进程处理
            {
                int peerfd = accept(listenfd, NULL, NULL);
                if (peerfd < 0)
                {
                    perror("accept");
                    exit(EXIT_FAILURE);
                }
                printf("parent peerfd: %d\n");
                    //查找子进程
                for (size_t j = 0; j < pnum; j++)
                {
                    if (pProcessData[j].busy == 0)
                    {
                        sendFd(pProcessData[i].fd, peerfd);
                        pProcessData[j].busy = 1;
                        break;
                    }
                }
                    //父进程必须关闭套接字,否则无法正常关闭peerfd
                close(peerfd);
            }
            else{
                //子进程完成任务,通过管道通知父进程
                int howmany = 0;
                int ret = read(fd, &howmany, sizeof(int));
                if(ret < 0){
                    perror("read");
                }
                pProcessData[i].busy = 0;
                printf("child %d is not busy.\n", pProcessData[i].pid );
            }
        }
            
            
    }

    return;
}

子进程流程

int childHandleTask(int pipefd){
    printf("child %d\n", getpid());
    while (1)
    {
        //子进程一直等待任务到来
        //当没有任务到的时候,就阻塞在recvFd上
        int childFd = -1;
        printf("child recvFd ...\n");
        recvFd(pipefd, &childFd);
        printf("child %d recv %d.\n", getpid(), childFd);

        //进行文件的发送
        char buf[64] = "hello,client";
        send(childFd, buf, strlen(buf), 0);

        //文件发送完成关闭连接
        close(childFd);
        //写管道通知父进程
        int one = 1;
        write(pipefd, &one, sizeof(int));

    }
    
}

int makeChild(pProcess_data_t pdata, int pnum){
    
    for (size_t i = 0; i < pnum; i++)
    {
        int fds[2];
        socketpair(AF_LOCAL, SOCK_STREAM, 0, fds);
        pid_t pid = fork();
        if (pid == 0)
        {
        //子进程
            close(fds[0]);
        //执行子进程任务
            childHandleTask(fds[1]);
            exit(EXIT_SUCCESS);
        }

    //父进程
        close(fds[1]);
        pdata[i].pid = pid;
        pdata[i].fd = fds[0];
        pdata[i].busy = 0;

    }
    
    return 0;
}

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

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

相关文章

Linux进程地址空间第三讲

至今为止&#xff0c; 我们所学到的大多数的知识&#xff0c; 包括语言&#xff0c; 数据结构&#xff0c; 动静态库等等的 都是在下面这3G&#xff0c; 也就是用户空间里的(进程等待&#xff0c; 信号之类的与内核有关的是在上面那1G里的) 所以对于我们来说&#xff0c; 我们…

避雷!5.3分,新增1区被标记On Hold,共12本SCI/SSCI慎投!

本周投稿推荐 SSCI • 2/4区经管类&#xff0c;2.5-3.0&#xff08;录用率99%&#xff09; SCIE&#xff08;CCF推荐&#xff09; • 计算机类&#xff0c;2.0-3.0&#xff08;最快18天录用&#xff09; SCIE&#xff08;CCF-C类&#xff09; • IEEE旗下&#xff0c;1/2…

贪吃蛇游戏(C语言实现)

目录 游戏效果展示文件代码的展示test.cSnake.cSnake.h 下一个坐标不是食物 游戏效果展示 QQ录屏20240507163633 文件 代码的展示 test.c #define _CRT_SECURE_NO_WARNINGS#include<locale.h> //设置本地化 #include"Snake.h"//游戏的测试逻辑 void test() {…

免单狂欢模式:电商销售的新风潮

免单狂欢模式&#xff0c;是电商行业里一股新兴的销售力量。它以其独特的激励机制、社交属性与合规运营&#xff0c;迅速吸引了众多消费者的目光&#xff0c;成为推动销售业绩飙升的强大动力。 一、合规运营&#xff0c;稳健发展 在免单狂欢模式中&#xff0c;我们严格遵守法律…

搭建Harbor仓库

文章目录 Harbor仓库搭建Harbor仓库安装 docker 服务修改配置文件 Harbor仓库 搭建Harbor仓库 下载 Harbor 仓库 安装 docker 服务 # step 1: 安装必要的一些系统工具 yum install -y yum-utils device-mapper-persistent-data lvm2 # Step 2: 添加软件源信息 yum-config-m…

NFCP502-W05 电流数据是多少安培?

YOKOGAWA NFCP502-W05 是一款由横河电机&#xff08;Yokogawa Electric Corporation&#xff09;生产的微型断路器&#xff08;Microcircuit Breaker&#xff0c;简称 MCB&#xff09;。 横河电机是一家日本的跨国公司&#xff0c;专注于自动化和控制系统、仪器和其他相关设备…

sh包装脚本

两个脚本,运行的时间间隔分别是一分钟和五分钟,放入到sh文件中,挂在后代,脚本里面的路径最好是绝对路径。 新建sh文件 新建 run_test.sh 文件,使其可以运行两个不同的 Python 脚本,一个每分钟运行一次,另一个每五分钟运行一次。下面是修改后的 run_test.sh 文件的示例:…

学QT的第二天~

小黑子鉴别界面 #include "mywidget.h" void MyWidget::bth1() { if(edit3 ->text()"520cxk"&&edit4 ->text()"1314520") { qDebug()<< "你好&#xff0c;真爱粉"; this->close(); } else { speecher->sa…

EMAIL-PHP功能齐全的发送邮件类可以发送HTML和附件

EMAIL-PHP功能齐全的发送邮件类可以发送HTML和附件 <?php class Email { //---设置全局变量 var $mailTo ""; // 收件人 var $mailCC ""; // 抄送 var $mailBCC ""; // 秘密抄送 var $mailFrom ""; // 发件人 var $mailSubje…

PyQt6--Python桌面开发(1.安装配置环境)

一.PyQt6简介 PyQt&#xff1a;PyQt是一个功能强大且成熟的GUI框架&#xff0c;基于Qt库。它提供了丰富的组件、布局和主题选项&#xff0c;以及强大的功能和灵活性。PyQt的优点是它具有现代化的外观和丰富的功能&#xff0c;适用于复杂的GUI应用程序。然而&#xff0c;由于Py…

Cobalt Strike DNS Beacon使用

0. 前言 1. 实验运行流程 2. 环境搭建 2.1.1 安装虚拟机软件VMware……大家应该都有装吧&#xff0c;这里就不教了 2.1.2 Windows 10虚拟机&#xff08;受害机&#xff09; 2.1.3 Ubuntu虚拟机&#xff08;攻击机&#xff09; 2.1 安装虚拟机 2.2 安装Java 2.3 安装Dock…

通过管理系统进行升级怎么选?

现在通过系统来做办公效率提升的又很多&#xff0c;但怎么选&#xff0c;确实很关键。 我们是在去年年初的时候进行企业系统化的。当时刚摘下口罩&#xff0c;领导也是意识到团队办公的不便&#xff0c;数据管理的混乱&#xff0c;业务流转的低效等原因&#xff0c;开始寻找各…

数据结构——链表专题3

文章目录 一、判断链表是否有环二、返回入环的第一个节点三、随机链表的复制 一、判断链表是否有环 原题链接&#xff1a;判断链表是否有环 这道题可以使用快慢指针&#xff0c;fast一次走两步&#xff0c;slow一次走一步&#xff0c;如果有环&#xff0c;它们在环里面必定会…

SAP-ABAP-视图

1、什么是视图&#xff1f; 当需要查询多个表中的某些字段的数据时&#xff0c;就可以使用视图。视图不影响数据库中的数据&#xff0c;仅作为查询手段或工具。 2、视图类型&#xff1a; 数据库视图和维护视图经常使用。 3、创建视图SE11 3.1、数据库视图 可以直接输入表名…

【半个月我拿下了软考证】软件设计师高频考点--系统化教学-计算机与组成原理

&#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;软件设计师考点暴击 ⭐&#x1f170;️进入狂砍分⭐ ⭐软件设计师高频考点文档&#xff0c; ⭐软件设计师高频考点专栏 ⭐⭐ &#x1f3b6;&#xff08;1) 考点6&#xff0c;流水线 考点&#xff1a;流水线相关的计算 可…

《QT实用小工具·六十》Qt 多列时间轴控件

1、概述 源码放在文章末尾 Qt 多列时间轴控件。 可与多段字符串格式自由转换&#xff0c;也可手动添加列表项。 专门用来以时间轴作为事件线发展顺序的故事大纲。 特点 时间背包功能&#xff1a;记录所有物品或属性发生的变化&#xff0c;随时回溯 时间可输入任意内容&…

linux学习:音视频编程+alsa声音架构

目录 概念 采样 量化 编码 音频文件wav 格式 标准音频接口 ALSA 录制音频 步骤 api 获取pcm设备句柄 设置 PCM 设备参数 代码 播放音频 步骤 代码 概念 信号都是模拟信号&#xff0c;不管是声音还是光线&#xff0c;这些模拟信号需要被 A/D 转换器转换成数字信…

RK3576芯片规格,以及与RK3588对比

瑞芯微RK3576是一款高性能、低功耗的SoC&#xff08;系统级芯片&#xff09;处理器&#xff0c;适用于基于ARM的PC、边缘计算设备、个人移动互联网设备等多种应用场景。它采用Arm架构的八核心CPU&#xff0c;集成了GPU、MCU、NPU、VPU等多种计算核心&#xff0c;并具有丰富的外…

我的256天之创作纪念日

目录 时光 数据的一些变化 开心的事 憧憬 时光 自上次CSDN的消息推送&#xff0c;又一个128天过去了&#xff0c;整天的工作和生活都在忙忙碌碌中度过&#xff0c;每到能静下来片刻&#xff0c;都倍感珍惜。因为一些原因&#xff0c;能够陪伴家人的时间越来越少&#xff…

【LLM 论文】OpenAI 基于对比学习微调 LLM 得到嵌入模型

论文&#xff1a;Text and Code Embeddings by Contrastive Pre-Training ⭐⭐⭐⭐ OpenAI 一、论文速读 这篇论文基于大型生成式 LLM 通过对比学习来微调得到一个高质量的 text 和 code 的 embedding 模型。 训练数据的格式&#xff1a;是一堆 ( x i , y i ) (x_i, y_i) (x…