Linux--进程间通信(2)(有名管道)

目录

1.原理

2.创建命名管道 

3.使用命名通道实现简单的通信

4.使用创建的命名管道 


1.原理

        匿名管道没有名称,它们是通过句柄在父进程和子进程之间传递的。这意味着匿名管道只能用于具有父子关系的进程之间。

        但如果程序之间没关系,那么这时候就要用到有名管道了,有名管道通过一个名称(通常是一个文件系统中的路径)来标识。这使得任何进程都可以通过该名称来访问管道,而不必是创建管道的进程的子进程。有名管道支持不同进程间的通信,甚至支持跨计算机(网络)的通信。有名管道的生命周期由创建它的进程控制,但即使创建它的进程终止,只要还有进程连接着管道,管道就会继续存在。

        命名管道在操作系统中表现为一种特殊类型的文件,它存在于系统的命名空间中,可以像打开文件那样被打开和读写。一旦创建,命名管道就可以在不同的进程中被打开多次,允许单向或双向的数据流传输。


2.创建命名管道 

创建命名管道,直接使用mkfifo命令就可以了

eg:

创建一个命名管道

        一号机上的while循环持续地将字符串"hello boy"写入到命名管道myfifo中,每次写入后暂停一秒。二号机上的cat命令则从myfifo中读取数据,并将其输出到标准输出。看一看效果:我们发现在一号机写到myfifo中的数据会被同步到二号机中的myfifo,

        两个不相关的进程(一号机和二号机上的进程)之间建立通信。这两个进程不需要有任何父子关系或其他特殊关系,只需要知道命名管道的文件路径即可。

        myfifo的文件大小始终都没有变,因为并没有被刷新到磁盘中。


3.使用命名通道实现简单的通信

提供一个关闭命名管道的函数:unlink

提供一个namepipe的类,它封装了命名管道的创建、打开、读写和删除的逻辑。以下是代码(namedPipe.hpp):

#pragma once#include <iostream>
#include <cstdio>
#include <cerrno>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>const std::string comm_path = "./myfifo";
#define DefaultFd -1
#define Creater 1
#define User 2
#define Read O_RDONLY
#define Write O_WRONLY
#define BaseSize 4096class NamePiped
{
private:bool OpenNamedPipe(int mode){_fd = open(_fifo_path.c_str(), mode);if (_fd < 0)return false;return true;}public:NamePiped(const std::string &path, int who): _fifo_path(path), _id(who), _fd(DefaultFd){if (_id == Creater){int res = mkfifo(_fifo_path.c_str(), 0666);if (res != 0){perror("mkfifo");}std::cout << "creater create named pipe" << std::endl;}}bool OpenForRead(){return OpenNamedPipe(Read);}bool OpenForWrite(){return OpenNamedPipe(Write);}int ReadNamedPipe(std::string *out){char buffer[BaseSize];int n = read(_fd, buffer, sizeof(buffer));if(n > 0){buffer[n] = 0;*out = buffer;}return n;}int WriteNamedPipe(const std::string &in){return write(_fd, in.c_str(), in.size());}~NamePiped(){if (_id == Creater){int res = unlink(_fifo_path.c_str());if (res != 0){perror("unlink");}std::cout << "creater free named pipe" << std::endl;}if(_fd != DefaultFd) close(_fd);}private:const std::string _fifo_path;int _id;int _fd;
};
  1. 成员变量
    • _fifo_path:存储命名管道的路径。
    • _id:标识该对象是命名管道的创建者(Creater)还是用户(User)。
    • _fd:文件描述符,用于与命名管道进行通信。初始化为DefaultFd(定义为-1)。
  2. 构造函数
    • 接收命名管道的路径和创建者/用户标识。
    • 如果_idCreater,则调用mkfifo函数在指定路径下创建命名管道。如果创建失败,会打印错误信息。
  3. OpenForRead和OpenForWrite方法
    • 这两个方法分别用于打开命名管道进行读取和写入操作。
    • 内部调用OpenNamedPipe方法,传入相应的读取或写入模式(O_RDONLYO_WRONLY)。
    • OpenNamedPipe方法使用open系统调用来打开命名管道,并保存文件描述符到_fd成员变量中。
  4. ReadNamedPipe和WriteNamedPipe方法
    • ReadNamedPipe方法从命名管道中读取数据到提供的字符串指针中。
    • WriteNamedPipe方法将提供的字符串写入命名管道。
    • 这两个方法都使用readwrite系统调用来执行实际的读写操作。
  5. 析构函数
    • 在对象销毁时,析构函数会被调用。
    • 如果_idCreater,则调用unlink函数来删除命名管道。这确保了命名管道在不再需要时从文件系统中被移除。
    • 无论_id的值如何,都会检查_fd是否不是DefaultFd(即文件描述符是否已打开),如果是,则调用close函数来关闭文件描述符。

接下来创建一个客户端向命名管道写入(client.cc):

#include "namedPipe.hpp"// write
int main()
{NamePiped fifo(comm_path, User);if (fifo.OpenForWrite()){std::cout << "client open namd pipe done" << std::endl;while (true){std::cout << "Please Enter> ";std::string message;std::getline(std::cin, message);fifo.WriteNamedPipe(message);}}return 0;
}

循环的写入信息。


创建一个客户端用来读取命名管道的信息(server.cc):

#include "namedPipe.hpp"int main()
{NamePiped fifo(comm_path, Creater);// 对于读端而言,如果我们打开文件,但是写还没来,我会阻塞在open调用中,直到对方打开// 进程同步if (fifo.OpenForRead()){std::cout << "server open named pipe done" << std::endl;sleep(3);while (true){std::string message;int n = fifo.ReadNamedPipe(&message);if (n > 0){std::cout << "Client Say> " << message << std::endl;}else if(n == 0){std::cout << "Client quit, Server Too!" << std::endl;break;}else{std::cout << "fifo.ReadNamedPipe Error" << std::endl;break;}}}return 0;
}
  • 如果ReadNamedPipe返回的值n大于0,表示成功读取了n个字符到message中。
    • 程序将输出"Client Say> "和读取到的消息内容。
  • 如果n等于0,通常表示客户端已经关闭了连接或者发送了一个EOF(文件结束符)。
    • 程序将输出"Client quit, Server Too!"并退出循环,然后退出程序。
  • 如果n小于0,表示读取过程中发生了错误。
    • 程序将输出"fifo.ReadNamedPipe Error"并退出循环,然后退出程序。

4.使用创建的命名管道 

 我们先运行了读端程序,但是并没有提示我们的读端创建成功(对于读端而言,如果我们打开文件,但是写还没来,我会阻塞在open调用中,直到对方打开)

打开写端,读端才成功打开。

这就实现进程间的通信了

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

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

相关文章

2024 年“泰迪杯”A 题:生产线的故障自动识别与人员配置--第四题(用遗传算法解决生产线排班问题--matlab代码)

问题背景&#xff1a; 问题四&#xff1a;根据实际情况&#xff0c;现需要扩大生产规模&#xff0c;将生产线每天的运行时间从 8 小时增加 到 24 小时不间断生产&#xff0c;考虑生产线与操作人员的搭配&#xff0c;制定最佳的操作人员排班方案&#xff0c;要求满足以下条件&am…

RedHat9网络配置设计

目录 一、实验目的 二、实验过程 1、配置新网络接口 2、多网卡配置网络 3、网络接口的绑定&#xff0c;进行远程访问 4、配置网络接口的组合 一、实验目的 本次实验的目的是使用nmcli命令工具配置网络&#xff0c;ens160配置多个网卡&#xff0c;进行网络接口的绑定与组合…

Redis 主从搭建简单教程

安装单机 首先拿到安装包 wget https://download.redis.io/releases/redis-7.0.15.tar.gz然后进行解压 tar -zxvf redis-7.0.15.tar.gz 然后创建一个文件夹myredis将原始配置文件进行备份 mkdir /myrediscp redis.conf /myredis/redis7.conf 将配置文件复制进去 最后使用vim编…

室内也可以用北斗定位?还能用RTK?

室内卫星顾名思义&#xff0c;就是在室内有遮挡环境中的卫星定位技术&#xff0c;众所周知&#xff0c;目前全球几大GNSS定位系统已经很完善&#xff0c;但是GNSS有个致命的弱点&#xff0c;就是地面如果有遮挡就没有信号&#xff0c;在这样的条件下&#xff0c;在室内定位场景…

RT_Thread内核源码分析(一)——CM3内核和上下文切换

目录 一、程序存储分析 1.1 CM3内核寻址空间映射 1.2 程序静态存储和动态执行 二、CM3内核相关知识 2.1 操作模式和特权极别 2.2 环境相关寄存器 2.2.1 通用寄存器组&#xff0c; 2.2.2 状态寄存器组 2.2.3 模式切换环境自动保存 2.2.4 函数调用形参位置 2.3 …

信息安全基础(补充)

&#xff09;的内容主要有数据备份、数据修复、系统恢复等。响应&#xff08;Respons&#xff09;的内容主要有应急策略、应急机制、应急手段、入侵过程分析及安全状态评估等。 面向数据挖掘的隐私保护技术主要解决高层应用中的隐私保护问题&#xff0c;致力于研究如何根据不同…

android studio 导入github里的项目后提示:Add Configuration

原文链接&#xff1a;https://blog.csdn.net/weixin_45677723/article/details/125940912 从github上面clone项目&#xff0c;出现下图问题&#xff1a; 解决问题&#xff1a; 我这个的情况是因为多文件嵌套了&#xff0c;我用Android Studio打开的是A文件&#xff0c;而B项…

移除重复节点

题目链接 移除重复节点 题目描述 注意点 链表未排序链表长度在[0, 20000]范围内链表元素在[0, 20000]范围内 解答思路 使用Set存储访问过的链表中出现的节点值&#xff0c;当遍历到链表的某个节点在Set中出现过&#xff0c;则需要将该节点的前一个节点next指针指向该节点的…

InternLM2-Math-Plus全面升级,全尺寸最强的开源数学模型

总览 数学能力是大语言模型推理水平的重要体现。上海人工智能实验室在推出领先的开源数学模型InternLM2-Math的三个月之后对其进行了升级&#xff0c;发布了全新的 InternLM2-Math-Plus。升级后的 InternLM2-Math-Plus 在预训练和微调数据方面进行了全面的优化&#xff0c;显著…

【二叉树】非递归实现前中后序遍历

目录 前言 算法思想 非递归实现前序遍历 过程分析 代码 非递归实现中序遍历 过程分析 代码 非递归实现后序遍历 过程分析 代码 前言 1&#xff09;前序&#xff1a;根 左子树 右子树 2&#xff09;中序&#xff1a;左子树 根 右子树 3&#xff09;后序&#xff1…

邮箱调用接口的服务有哪些?怎么配置接口?

邮箱调用接口安全性如何保障&#xff1f;使用邮箱服务器的方法&#xff1f; 邮箱调用接口为各种应用和系统提供了便捷的电子邮件发送与接收功能。选择合适的邮箱调用接口服务可以大大提升工作效率和用户体验。本AokSend将探讨一些主要的邮箱调用接口服务。 邮箱调用接口&…

MySQL(进阶)--索引

目录 一.存储引擎 1.MySQL体系结构​编辑 2.存储引擎简介 3.存储引擎特点 (1.InnoDB (2.MyISAM (3.Memory 4.存储引擎选择 二.索引 1.索引概述 2.索引结构 3.索引分类 4.索引语法 (1.创建索引 (2.查看索引 (3.删除索引 5.SQL性能分析 (1.SQL执行频率 (2.慢查…

【Sql Server】随机查询一条表记录,并重重温回顾下自定义函数的封装和使用

大家好&#xff0c;我是全栈小5&#xff0c;欢迎来到《小5讲堂》。 这是《Sql Server》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 前言随机查询语…

Android 中资源文件夹RES/RAW和ASSETS的使用区别

文章目录 1、res/raw 文件夹1.1、特点1.2、使用方法1.3、示例&#xff1a; 2. assets 文件夹2.1、特点2.2、使用方法2.3、示例&#xff1a; 3、使用场景3.1、res/raw 使用场景3.2、assets 使用场景 4、比较与选择5、文件夹选择的建议6、 示例代码总结6.1、res/raw 示例6.2、ass…

电瓶车进电梯识别报警摄像机

随着电动车的普及&#xff0c;越来越多的人选择电动车作为出行工具。在诸多场景中&#xff0c;电梯作为一种常见的交通工具&#xff0c;也受到了电动车用户的青睐。然而&#xff0c;电动车进入电梯时存在一些安全隐患&#xff0c;为了提高电动车进电梯的安全性&#xff0c;可以…

小程序自动化辅助渗透脚本(2024)

简介 1.还在一个个反编译小程序吗&#xff1f; 2.还在自己一个个注入hook吗&#xff1f; 3.还在一个个查看找接口、查找泄露吗&#xff1f; 现在有自动化辅助渗透脚本了&#xff0c;自动化辅助反编译、自动化注入hook、自动化查看泄露 注&#xff1a;本工具仅用于学习交流&…

Java中的JSON神器,如何轻松玩转复杂数据结构

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 一、揭秘JSON世界的基石 在Java的世界中&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;它基于文本&#xff0c;易于阅读和编写&#xff0c;同时也易于…

站内信设计

参考文章&#xff1a;https://cloud.tencent.com/developer/article/1684449 b站站内信业务设计&#xff1a; 消息的类型分为&#xff1a; 1、系统消息 2、、点赞、回复等用户行为之间的消息(事件提醒) 3、用户之间的消息 系统消息 用一个用户消息表可以吗&#xff1f; 可…

XS2185一款八通道以太网供电控制器

XS2185是一款八通道以太网供电控制器。 XS2185通过侦测各通道的DET管脚输入电压 来判断是否有合格的负载/PD接入系统&#xff0c;以决定 是否开启MOS供电开关。 当通道已经处于供电状态时&#xff0c;XS2185通过侦 测SENSE管脚的输入电压&#xff0c;以判断供电是否发生 …

免费,Python蓝桥杯等级考试真题--第15级(含答案解析和代码)

Python蓝桥杯等级考试真题–第15级 一、 选择题 答案&#xff1a;B 答案&#xff1a;D 解析&#xff1a;集合的并集运算有两种方式&#xff0c;一种是使用“|”运算符进行操作&#xff0c;另一种是使用union()方法来实现&#xff0c;故答案为D。 答案&#xff1a;A 解析&…