当前位置: 首页 > news >正文

【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;
}

在这里插入图片描述


未完待续

相关文章:

【Linux】进程间通信_2

文章目录 七、进程间通信1. 进程间通信分类管道 未完待续 七、进程间通信 1. 进程间通信分类 管道 管道的四种情况&#xff1a; ①管道内部没有数据&#xff0c;并且具有写端的进程没有关闭写端&#xff0c;读端就要阻塞等待&#xff0c;知道管道pipe内部有数据。 ②管道内部…...

Linux基础 - 常用命令

目录 零. 简介 一 . 常见 Ubuntu 命令 二. apt-get 下载 三. 网络命令 四. 常用命令的总结 零. 简介 在 Ubuntu 中&#xff0c;命令是用于与操作系统进行交互和执行各种操作的指令。通过在终端中输入命令&#xff0c;可以完成文件管理、系统配置、软件安装、进程管理等各种…...

轻松两步,借助向量数据库 VectorDB 与千帆 Appbuilder 构建个性化本地问答知识库

在我们日常的工作和生活中&#xff0c;经常会遇到需要快速获取和管理大量信息的情况。无论是解答客户的问题&#xff0c;还是整理公司内部的资料&#xff0c;一个高效的知识库系统都能帮我们省下大量时间和精力。 为了帮助大家快速构建 RAG 应用&#xff0c;我们之前发布了一个…...

ONLYOFFICE 桌面编辑器 8.1

ONLYOFFICE 桌面编辑器 8.1 ONLYOFFICE 简介一、轻松编辑器 PDF 文件二、用幻灯片版式快速修改幻灯片三、无缝切换文档编辑、审阅和查看模式四、**改进从右至左语言的支持 & 新的本地化选项**五、隐藏“连接到云”板块六、在演示文稿中播放视频和音频文件七、版本 8.1&…...

idea中的git在clone文件提示 filename too long

一 解决版本 1.1 问题描述以及解决办法 当在Windows系统下使用Git时出现“filename too long”错误&#xff1a; git config --system core.longpaths true...

C++ 数组介绍

1. 数组是什么&#xff1f; 在C中&#xff0c;数组是一种基本的数据结构&#xff0c;它允许我们存储固定大小的相同类型元素的集合。每个元素在数组中都有一个唯一的索引&#xff0c;从0开始。 2. 数组的声明与初始化 2.1 声明数组 声明数组时&#xff0c;需要指定数组的类…...

思维导图MindManager2024最新版,让你的思维飞起来!

亲爱的朋友们&#xff0c;今天我要跟大家分享一款我近期深度使用并彻底被种草的神器——MindManager2024最新版本的思维导图软件。作为一位对效率和创意有着极高追求的内容创作者&#xff0c;我几乎尝试过市面上所有的思维导图工具&#xff0c;而MindManager2024无疑是其中的佼…...

Spring容器启动流程——refresh()单个方法分析

文章目录 Spring启动过程this()方法refresh()prepareRefresh()obtainFreshBeanFactory()prepareBeanFactory()postProcessBeanFactory()invokeBeanFactoryPostProcessorsregisterBeanPostProcessorsinitMessageSource()initApplicationEventMulticaster()onRefresh()registerLi…...

Redis--注册中心集群 Cluster 集群

准备工作&#xff1a; 首先pull用到的镜像 docker pull redis:6.0.8 端口准备 node01 192.168.248.189.6381-6382 node02 192.168.248.190 6383-6384 node03 192.168.248.191 6385-6386 创建路径&#xff1a; mkdir -p /soft/docker/redis-cluster cd /soft/docker/re…...

秋招突击——6/20——复习{(单调队列优化)——最大子序列和,背包问题——宠物小精灵收服问题}——新作{两两交换链表中的节点}

文章目录 引言复习单调队列优化——最大子序列和思路分析实现代码参考实现 背包问题——宠物小精灵的收服问题个人实现参考实现 新作两两交换链表中的节点个人实现参考实现 删除有序数组中的重复项个人实现知识补全迭代器的访问和控制vector删除特定的元素erasevector底层删除元…...

使用 MongoDB 剖析开放银行:技术挑战和解决方案

开放银行&#xff08;或开放金融&#xff09;在银行业掀起了一股颠覆性浪潮&#xff0c;它迫使金融机构&#xff08;银行、保险公司、金融科技公司、企业甚至政府机构&#xff09;迎接一个透明、协作和创新的新时代。这种模式转变要求银行与第三方提供商&#xff08;TPP&#x…...

鸿蒙 HarmonyOS NEXT星河版APP应用开发-阶段二

一、鸿蒙应用界面开发 弹性布局-Flex 语法 /* 弹性容器组件 Flex() 位置&#xff1a; Flex默认主轴水平往右&#xff0c;交叉轴垂直向下&#xff08;类似Row&#xff09; 语法&#xff1a; Flex(参数对象){子组件1,子组件2,子组件3 } 属性方法&#xff1a; direction&#xf…...

26.4 Django 视图层

1. 视图函数 视图函数是Django框架中用于处理Web请求并返回Web响应的重要组件. 以下是对Django视图函数的详细解释: * 1. 视图函数与URL的映射.为了让Django能够知道哪个URL对应哪个视图函数, 需要在应用的urls.py文件中定义URL模式.使用path或re_path函数来定义URL模式, 并将…...

Hbase介绍

Hbase介绍 HBase 是一个开源的、分布式的、面向列的 NoSQL 数据库系统&#xff0c;它建立在 Apache Hadoop 之上&#xff0c;提供了高可靠性、高性能、可伸缩性和高可用性的存储解决方案。让我来简单介绍一下 HBase 的架构。 1. 架构概述&#xff1a; HBase 的架构设计基于 Go…...

rollup学习笔记

一直使用的webpack,最近突然想了解下rollup,就花点时间学习下. 一,什么是rollup? rollup 是一个 JavaScript 模块打包器&#xff0c;可以将小块代码编译成大块复杂的代码,比如我们的es6模块化代码,它就可以进行tree shaking,将无用代码进行清除,打包出精简可运行的代码包. 业…...

多商户零售外卖超市外卖商品系统源码

构建你的数字化零售王国 一、引言&#xff1a;数字化零售的崛起 在数字化浪潮的推动下&#xff0c;零售业务正经历着前所未有的变革。多商户零售外卖超市商品系统源码应运而生&#xff0c;为商户们提供了一个全新的数字化零售解决方案。通过该系统源码&#xff0c;商户们可以…...

HTML 教程

HTML 教程 HTML(HyperText Markup Language)是一种用于创建网页的标准标记语言。它描述了一个网站的结构骨架,使得浏览器能够展示具有特定格式的文本、链接、图片和其他内容。本教程将带你深入了解HTML的基础知识,包括其语法、常用标签以及如何构建一个基本的网页结构。 …...

【仿真建模-解析几何】求有向线段上距指定点最近的坐标

Author&#xff1a;赵志乾 Date&#xff1a;2024-06-25 Declaration&#xff1a;All Right Reserved&#xff01;&#xff01;&#xff01; 问题描述&#xff1a; 有向线段起点A为&#xff08;x1&#xff0c;y1&#xff09;&#xff0c;终点B为&#xff08;x2&#xff0c;y2&a…...

Linux系统中常用的基本命令

1. 文件与目录管理 ls: 列出目录内容。cd: 切换当前工作目录。pwd: 显示当前工作目录的路径。mkdir: 创建一个新目录。rmdir: 删除空目录。cp: 复制文件或目录。mv: 移动或重命名文件或目录。rm: 删除文件或目录。touch: 创建一个空文件或更新文件时间戳。 2. 文本内容查看 …...

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

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

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

【PX4飞控】mavros gps相关话题分析,经纬度海拔获取方法,卫星数锁定状态获取方法

使用 ROS1-Noetic 和 mavros v1.20.1&#xff0c; 携带经纬度海拔的话题主要有三个&#xff1a; /mavros/global_position/raw/fix/mavros/gpsstatus/gps1/raw/mavros/global_position/global 查看 mavros 源码&#xff0c;来分析他们的发布过程。发现前两个话题都对应了同一…...

Android Framework预装traceroute执行文件到system/bin下

文章目录 Android SDK中寻找traceroute代码内置traceroute到SDK中traceroute参数说明-I 参数&#xff08;使用 ICMP Echo 请求&#xff09;-T 参数&#xff08;使用 TCP SYN 包&#xff09; 相关文章 Android SDK中寻找traceroute代码 设备使用的是Android 11&#xff0c;在/s…...

【字节拥抱开源】字节团队开源视频模型 ContentV: 有限算力下的视频生成模型高效训练

本项目提出了ContentV框架&#xff0c;通过三项关键创新高效加速基于DiT的视频生成模型训练&#xff1a; 极简架构设计&#xff0c;最大化复用预训练图像生成模型进行视频合成系统化的多阶段训练策略&#xff0c;利用流匹配技术提升效率经济高效的人类反馈强化学习框架&#x…...

【计算机网络】NAT、代理服务器、内网穿透、内网打洞、局域网中交换机

&#x1f525;个人主页&#x1f525;&#xff1a;孤寂大仙V &#x1f308;收录专栏&#x1f308;&#xff1a;计算机网络 &#x1f339;往期回顾&#x1f339;&#xff1a;【计算机网络】数据链路层——ARP协议 &#x1f516;流水不争&#xff0c;争的是滔滔不息 一、网络地址转…...

code-server安装使用,并配置frp反射域名访问

为什么使用 code-server是VSCode网页版开发软件&#xff0c;可以在浏览器访问编程&#xff0c;可以使用vscode中的插件。如果有自己的服务器&#xff0c;使用frp透传后&#xff0c;域名访问在线编程&#xff0c;使用方便&#xff0c;打开的服务端口不需要单独配置&#xff0c;可…...