【Linux】进程间通信_2

文章目录

  • 七、进程间通信
    • 1. 进程间通信分类
      • 管道
  • 未完待续


七、进程间通信

1. 进程间通信分类

管道

管道的四种情况:

①管道内部没有数据,并且具有写端的进程没有关闭写端,读端就要阻塞等待,知道管道pipe内部有数据。
②管道内部被写满,并且具有读端的继承没有关闭读端,写端写满管道pipe后,就需要阻塞等待,直到管道清空。
③对于写端而言:关闭了写端管道,读端会将管道pipe中的数据读完,最后会读到返回值0,表示读取完毕。
④对于读端而言:关闭了读端管道,操作系统会直接终止具有写端的进程,通过十三号信号 SIGPIPE 杀掉进程。

在这里插入图片描述
管道的五种特性:

①自带同步机制
②通过血缘关系进程进行通信,常见为父子进程
③pipe是面向字节流的
④父子退出,管道自动释放,文件的生命周期是随进程的
⑤管道只能单向通信

我们曾经学的命令行管道 | 本质上就是pipe。
接下来我们根据我们所学的管道知识来实现一个 进程池
Makefile

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

任务文件 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 : print log task\n" << endl;
}void ReloadConf(int fd, pid_t pid)
{cout << "sub process: " << pid << ", fd : " << fd << ", task is : reload conf task\n" << endl;
}void ConnectMysql(int fd, pid_t pid)
{cout << "sub process: " << pid << ", fd : " << fd << ", task is : connect mysql task\n" << endl;
}// 任务列表
task_t tasks[3] = {PrintLog, ReloadConf, ConnectMysql};// 随机选择一个任务
uint32_t NextTask()
{return rand() % 3;
}// 执行任务
void worker(int fd)
{while (true){uint32_t task_id = 0;ssize_t n = read(0, &task_id, sizeof(task_id));if (n == sizeof(task_id)){if (task_id >= 3) continue;tasks[task_id](fd, getpid());}else if (n == 0){cout << "sub process: " << getpid() << " exit" << endl;break;}}
}

进程池主逻辑 processpool.cc

#include <iostream>
#include <string>
#include <unistd.h>
#include <cstdlib>
#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 << " number of processes" << endl;
}// 将信道信息封装成一个类
class Channel
{
public:Channel(int wfd, pid_t sub_id, const string &name): _wfd(wfd), _sub_process_id(sub_id), _name(name){}string name(){return _name;}int wfd(){return _wfd;}pid_t pid(){return _sub_process_id;}void Close(){close(_wfd);}~Channel() {}
private:// 信道的写端int _wfd;// 子进程的idpid_t _sub_process_id;// 信道的编号名称string _name;
};// 进程池管理类
class ProcessPool
{
public:ProcessPool(int num_processes): _num_processes(num_processes){}// 创建子进程和信道int CreateProcess(work_t work){for (int i = 0; i < _num_processes; i++){// 创建管道int pipefd[2]{0};int n = pipe(pipefd);if (n < 0)return PipeError;// 创建子进程pid_t id = fork();if (id == 0){// 这里是子进程, 读端close(pipefd[1]);// 这里需要注意的是, 子进程需要从父进程那里接收任务, 所以需要将父进程的写端重定向到标准输入dup2(pipefd[0], 0);// 子进程执行任务work(pipefd[0]);exit(0);}string cname = "Channel-" + to_string(i);// 这里是父进程, 写端close(pipefd[0]);// 放到vector中管理起来_channels.push_back(Channel{pipefd[1], id, cname});}return 0;}// 向下一个信道发送任务(目的是负载均衡)int NextChannel(){static int next = 0;int c = next++;next %= _num_processes;return c;}// 向index进程执行code任务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){// 父进程关闭写端,子进程读端读到0会自动结束进程c.Close();cout << c.name() << " close done," << " sub process id: " << c.pid() << endl;}}// 等待所有子进程退出void WaitAll(){for (auto& c : _channels){pid_t pid = c.pid();// 回收子进程返回信息pid_t rid = waitpid(pid, nullptr, 0);if (rid == pid){cout << c.name() << " sub process id: " << c.pid() << " exit done" << endl;}}}~ProcessPool() {}
private:// 进程池的大小int _num_processes;// 信道管理容器vector<Channel> _channels;
};// 控制进程池
void CtrlProcessPool(ProcessPool* pp, int cnt)
{while (cnt){// 选择通道int c = pp->NextChannel();// 选择任务uint32_t code = NextTask();// 发送任务到子进程pp->SendTaskCode(c, code);sleep(1);cnt--;}
}int main(int argc, char *argv[])
{if (argc != 2){Usage(argv[0]);return UsageError;}int num_processes = std::stoi(argv[1]);if (num_processes < 1 || num_processes > 5)return ArgError;srand((unsigned)time(nullptr));// 创建进程池对象ProcessPool* pp = new ProcessPool(num_processes);// 创建子进程和信道pp->CreateProcess(worker);// 控制子进程执行指定数量的任务CtrlProcessPool(pp, 10);// 让所有的子进程退出pp->KillAll();// 回收子进程资源pp->WaitAll();return 0;
}

在这里插入图片描述


未完待续

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

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

相关文章

linux的centos系统安装docker

文章目录 一. 安装Docker1. 安装yum-utils包2. 配置Docker yum源3. 安装 Docker CE4. 启动并设置 Docker 开机自启5. 验证Docker安装 二. 配置镜像加速器 一. 安装Docker 1. 安装yum-utils包 sudo yum install -y yum-utils2. 配置Docker yum源 官网源&#xff0c;在没有外网…

【C#_For循环_二重循环_数组和排序等_二分搜索_第二篇】

C#(编程入门) 续上一篇:练习来自腾讯课堂免费课程3.1.For循环基本概念输出1-10For循环流程图如下计算1-10之和计算1-10的乘积3.2.for语句3.3.二重循环3.4.Break VS Continue3.5.案例:ATM机3.5.1.ATM机业务流程3.6.案例:21点3.7.抽奖程序4.1.输入数组元素4.2.数组与内存的关…

Redis数据库(二):Redis数据库的五种基本数据类型

Redis 是一个开源的内存数据库&#xff0c;支持多种数据结构&#xff0c;常用于缓存、会话管理、实时分析等场景。Redis 提供了五种基本的数据类型&#xff1a;字符串、 列表、 集合、 散列/哈希、 有序集合。这篇博客&#xff0c;我们来详细介绍这五种数据类型&#xff0c;并且…

【Flink metric(2)】chunjun的metric系统是怎么设计的:如何注册metric、如何同步metric

文章目录 一. 管理&#xff08;注册、同步&#xff09;metric1. BaseRichInputFormat对metric的管理2. 通过BaseMetric管理metric 二. AccumulatorCollector&#xff1a;metric同步1. 启动线程池&#xff0c;周期性更新metric信息2. 获取全局指标、本地指标3. 资源回收 三. 小结…

【产品经理】订单处理8-智能分仓

在电商ERP系统中&#xff0c;通常智能分仓策略是系统中最重要的功能之一&#xff0c;大公司若仓库较多时&#xff0c;智能分仓策略中也会加入大数据团队&#xff0c;通过算法来计算最优仓库。 本次讲解的智能分仓适用于中小公司&#xff0c;适合拥有2个以上10个以下仓库的公司…

AGI 之 【Hugging Face】 的[ 简单介绍 ] [ 基础环境搭建 ] 的简单整理

AGI 之 【Hugging Face】 的[ 简单介绍 ] [ 基础环境搭建 ] 的简单整理 目录 AGI 之 【Hugging Face】 的[ 简单介绍 ] [ 基础环境搭建 ] 的简单整理 一、简单介绍 二、Hugging Face 三、环境搭建 python 环境的搭建 Pycharm 环境搭建 1、下载 Pycharm 安装包 2、安装 …

装机必备一WinRAR安装使用以及常见问题

WinRAR是一款功能强大的压缩包管理器&#xff0c;支持多种压缩格式&#xff0c;如RAR、ZIP等。作为一款经典且广泛使用的压缩软件&#xff0c;WinRAR不仅在文件压缩率和速度方面表现出色&#xff0c;还提供了备份数据、缩减电子邮件附件大小以及解压缩网络下载文件等功能。 为…

数据结构与算法:回溯算法约束条件:剪枝详解、示例(C#、C++)与回溯典型例题详解

文章目录 一、约束条件二、剪枝三、典型例题四、常用术语五、示例N 皇后问题 C# 示例N 皇后问题 C 示例 六、常见用用回溯算法解决的问题汇总组合问题&#xff1a;图论问题&#xff1a;棋盘游戏问题&#xff1a;优化问题&#xff1a;调度问题&#xff1a;其他问题&#xff1a; …

How to persist LangChain conversation memory (save and load)

题意&#xff1a;如何持久化 LangChain 对话记忆&#xff08;保存和加载&#xff09; 问题背景&#xff1a; Im creating a conversation like so: 我正在创建一个对话&#xff0c;如下所示&#xff1a; llm ChatOpenAI(temperature0, openai_api_keyOPENAI_API_KEY,…

【CTF】BUU BURP COURSE 11

打开靶机之后&#xff0c;显示只能在本地打开&#xff08;一度以为靶机出问题&#xff09;。 解题步骤&#xff1a; 1.分析请求包信息 2.构建本地请求IP X-Real-IP&#xff1a;记录真实客户端IP地址信息&#xff1b; X-Forward-for&#xff1a;记录了请求IP到目标ip所经历的…

新型基坑气膜:施工开挖的得力干将—轻空间

随着城市建设的加速推进&#xff0c;施工过程中的环境问题日益受到关注。新型基坑气膜以其卓越的防尘、降噪、节能和防火功能&#xff0c;成为施工开挖领域中的得力干将&#xff0c;极大地提升了绿色施工的水平。 基坑气膜的作用 基坑气膜在施工现场形成了一个完全封闭的作业空…

Java EE之Servlet

Servlet 是 Java EE&#xff08;Java Platform, Enterprise Edition&#xff09;规范中的一个技术&#xff0c;是服务器端 Java 程序&#xff0c;用于处理客户端请求并生成动态响应。Servlet 通常用于构建 Web 应用程序&#xff0c;并与 HTTP 协议紧密集成。以下是对 Servlet 的…

JavaWeb系列七: 动态WEB开发核心(Servlet) 下

韩老师学生 ServletConfigServletContext网站计数器 HttpServletRequest细节1细节2细节3 Dispathcer请求转发应用实例请求转发细节和注意事项习题 HttpServletResponse请求重定向请求重定向注意事项动态获取到application context练习题 ServletConfig ●ServletConfig基本介绍…

docker --restart 容器重启策略

官网连接&#xff1a;https://docs.docker.com/config/containers/start-containers-automatically/ 当容器退出后&#xff0c;或者docker程序重启了&#xff0c;容器是否要重启&#xff0c;可以用重启策略控制。 用docker run命令的时候&#xff0c;用--restart 设置容器重启…

1.文件上传漏洞渗透及防御(OWASP实战训练)

1.文件上传漏洞渗透及防御&#xff08;OWASP实战训练&#xff09; OWASPupload上传漏洞实验一&#xff1a;低安全模式下&#xff0c;上传任意类型的文件&#xff0c;文件大小不受限制实验二&#xff0c;安全级别调整将其变为中等安全级别实验三&#xff1a;将其设为高安全级别 …

【教程】如何一步一步训练一个SOM神经网络-自组织竞争神经网络(Self-organizing Feature Map)

本文来自《老饼讲解-BP神经网络》https://www.bbbdata.com/ 目录 一、什么是SOM神经网络1.1.SOM神经网络有什么用1.2.SOM神经网络是如何聚类的 二、如何训练一个SOM神经网络2.1. 训练一个SOM神经网络的代码示例2.2. 如何查看SOM神经网络的聚类中心 SOM神经网络全称为自组织竞争…

《系统架构设计师教程(第2版)》第11章-未来信息综合技术-05-数字孪生体(Digital Twin)技术概述

文章目录 1. 数字孪生体发展历程1.2 准备期1.2 概念产生期1.3 领先应用期1.4 深度开发和大规模扩展应用期 2. 数字孪生体的定义3. 数字孪生体的关键技术3.1 建模3.2 仿真技术3.3 其他技术 4. 数字孪生体的应用4.1 制造领域4.2 全产业链上的应用4.3 城市4.4 战场 1. 数字孪生体发…

解决Java中的NoSuchAlgorithmException异常的技术实践

解决Java中的NoSuchAlgorithmException异常的技术实践 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 在Java编程中&#xff0c;NoSuchAlgorithmException异常…

Redis-主从复制-测试主从模式下的读写操作

文章目录 1、在主机6379写入数据2、在从机6380上写数据报错3、从机只能读数据&#xff0c;不能写数据 1、在主机6379写入数据 127.0.0.1:6379> keys * (empty array) 127.0.0.1:6379> set uname jim OK 127.0.0.1:6379> get uname "jim" 127.0.0.1:6379>…

【机器学习】python之人工智能应用篇——3D生成技术

在Python中&#xff0c;人工智能&#xff08;AI&#xff09;与3D生成技术的结合可以体现在多个方面&#xff0c;比如使用AI算法来优化3D模型的生成、通过机器学习来预测3D模型的属性&#xff0c;或者利用深度学习来生成全新的3D内容。然而&#xff0c;直接通过AI生成完整的3D模…