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

【Linux】命名管道

一、命名管道的原理

       在前面的博客中,我们学习了匿名管道,了解到了两个具有血缘关系的进程之间是如何进行通信的?那么在没有血缘关系(毫不相关)的进程之间是如何进行通信的?

       大致思路是一样的,我们还是需要能够进行让两个进程之间可以看到同一份资源,然后在同一份资源中进行读写和通信。如何让两个进程看见同一份文件呢??由于在Linux系统中,Linux的树形结构保证了一个文件只有一个唯一的路径。我们可以根据文件的路径来找到同一份文件。

二、使用指令来看一下命名管道

在man手册中,可以查到指令的命名管道:

mkfifo  XXXX

       我们可以进行通信,复制一下终端,利用两个终端进行通信:在一个终端中利用echo来打印到屏幕中,用另一个终端进行接收显示。

// 循环打印到命名管道的命令为:
while :; do echo "Hello world" ; sleep 1; done > myfifo// 接收的命令为:
cat < myfifo

在一个过程中有两个细节:

1. 在向命名管道中写入时,管道中的容量大小怎么进行改变?

为什么会有上面的现象呢??

       命名管道和匿名管道一样,都是内存文件,只不过命名管道在磁盘有一个简单的映像,但这个映像的大小永远为0,因为命名管道和匿名管道都不会将通信数据刷新到磁盘当中。

2. 我在接收端将读端进行关闭,为什么进程会直接退出呢?

       在之前的匿名管道的博客中,我们知道:读端直接关闭,写端一直在写,写端进程会被操作系统直接使用13号信号进行关闭,相当于程序出现异常。因为echo是内建命令,是有bash进程进行控制的。当我们终止掉读端进程后,因为写端执行的循环脚本是由命令行解释器bash执行的,所以此时bash就会被操作系统杀掉,我们的云服务器也就退出了

三、命名管道的代码

       现在,我们使用代码来创建一个命名管道,具体代码如下:

3.1 先来介绍一下使用的函数

3.1.1 mkfifo函数

函数的原型:

函数的参数部分:

  • pathname:创建管道文件的文件路径
  • mode:存放创建管道文件的权限 

函数的返回值:

  • 如果函数成功返回0,如果失败返回-1

函数的功能:

  • 该函数用于在文件系统中创建一个文件,该文件用于提供FIFO功能,即命名管道。

3.1.2 unlink函数

函数的原型:

函数的参数部分:

  • pathname:创建管道文件的文件路径

函数的返回值:

  • 函数的返回值为 0 表示成功,-1 表示失败,并设置相应的错误码。

函数的功能:

  • 该函数用于删除文件系统中的文件。它通过删除文件系统中文件的链接,从而使文件系统中不再存在该文件的链接。
  • 当所有链接(包括硬链接和符号链接)都被删除之后,文件系统便会回收文件占用的磁盘空间。
  • 需要注意的是,删除文件并不会立即释放文件的磁盘空间,而是在文件的引用计数为零时才会真正回收空间。

3.1.3 open函数

函数的原型:

函数的参数:

  • pathname:创建管道文件的文件路径
  • flags:一些标志位,我们需要认识一些标志位,这些标志位通过按位与进行传参,我们需要通过位图的知识点来将每一个标志位进行分开,分别进行不同函数的操作。open函数的一些标志位的写法和用途:

函数的返回值:

  • 调用成功时返回一个文件描述符fd,调用失败时返回-1,并修改errno

函数的功能: 

  • 打开文件

3.1.4 write函数

3.1.5 read函数

3.2 命名管道类的编写

3.2.1 创建命名管道的代码编写

const std::string comepath = "./myfifo"; // 先确定要打开的文件路径int CreateNamePipe(const std::string &path)
{int res = mkfifo(path.c_str(), 0666); // 在相应的路径创建管道文件,并设置其权限if (res != 0){perror("mkfifo");std::cerr << "errno:" << errno << std::endl;}return res;
}

3.2.2 删除管道文件的代码编写

int RemoveNamePipr(const std::string &path)
{int res = unlink(path.c_str());if (res != 0){perror("RemoveNamePipe");}return res;
}

3.2.3 最后将两个函数进行整合

class NamePipe
{
public:// 创建管道NamePipe(const std::string &path, int who): fifo_pipe(path), _id(who), _fd(default){if (_id == Creater){int res = mkfifo(path.c_str(), 0666);if (res != 0){perror("mkfifo");}std::cout << "Craeter create name pipe" << std::endl;}}// 销毁管道~NamePipe(){if (_id == Creater){int res = unlink(fifo_pipe.c_str());if (res != 0){perror("RemoveNamePipe");}std::cout << "Create free name pipe" << std::endl;}if(_fd != default) close(_fd);}private:const std::string &fifo_pipe;  // 存放管道文件的路径int _id;   // 检查是创建者还是使用者int _fd;   // 存放文件描述符
};

3.3 打开管道文件的代码编写

       我们已经知道了文件的路径,这时,我们需要调用open函数来进行文件的打开,并且表示是以读的形式打开,还是以写的形式打开。利用系统调用函数,将管道文件打开。

bool opennamepipe(int mode)
{_fd = open(fifo_pipe.c_str(), mode);  // mode传递的是标志位if (_fd < 0){return false;}return true;  // _fd是文件描述符
}

3.4 以读的形式或者以写的形式打开文件的代码编写

在打开文件的open函数中有一个标志位,我们可以使用标志位对文件进行不同的操作。

#define Read O_RDONLY  // 标志位
#define Write O_WRONLY// 以读的形式打开
bool openforread()
{return opennamepipe(Read);
}// 以写的形式打开
bool operforwrite()
{return opennamepipe(Write);
}

3.5 读管道和写管道

// 读管道
int ReadNamePipe(std::string *out)
{char buff[Basesize];int n = read(_fd, buff, sizeof buff);if(n > 0){buff[n] = '\0';*out = buff;}return n;
}// 写管道
int WriteNamePipe(const std::string& in)
{return write(_fd, in.c_str(), in.size());
}

3.6 编写发送端和接收端的代码编写

读端的代码:

#include "namedpipe.hpp"// server进行读取,管理命名管道的整个生命周期
int main()
{// 创建管道NamePipe fifo(comepath, Creater);// 对于读端而言,如果我们打开文件,但是写端还没来,我会阻塞在open调用中,直到对方打开// 进程同步,if (fifo.openforread()){while (true){std::string message;int n = fifo.ReadNamePipe(&message);if (n > 0){std::cout << "Client sat:" << message << std::endl;}else if(n == 0){std::cout << "Client quit, server too" << std::endl;break;}else{std::cout << "fifo.ReadNamePipe error" << std::endl;break;}}}return 0;
}

写端的代码:

#include "namedpipe.hpp"int main()
{NamePipe fifo(comepath, User);if (fifo.operforwrite()){while (true){std::cout << "Plass Enter:" << std::endl;std::string message;std::getline(std::cin, message);fifo.WriteNamePipe(message);}}return 0;
}

有一个细节

3.7 对代码进行进一步的修改

使得代码中管道的释放可以顺序进行。

四、回归概念

       最后,我们在来复盘一下匿名管道和命名管道。让不同的进程看到同一份资源,匿名管道和命名管道的区别是:匿名管道是父子间继承的方式来进行看到同一份管道资源,而命名管道是通过文件的唯一路径来看到同一份管道资源。

相关文章:

【Linux】命名管道

一、命名管道的原理 在前面的博客中&#xff0c;我们学习了匿名管道&#xff0c;了解到了两个具有血缘关系的进程之间是如何进行通信的&#xff1f;那么在没有血缘关系&#xff08;毫不相关&#xff09;的进程之间是如何进行通信的&#xff1f; 大致思路是一样的&#xff0c;我…...

IMX6Q基于linux4.1.15调试音频芯片tas2505

IMX6Q基于linux4.1.15调试音频芯片tas2505 1、开发环境2、初步想法3、开发过程4、tas2505重要的寄存器5、遇到的问题1、开发环境 芯片:IMX6Q (NXP系列) 内核版本:linux4.1.15 Ubuntu版本:16.04 目标模块:tas2505 2、初步想法 由于该电路是由外部晶振提供的时钟频率24.5…...

卷积常用网络

目录 1.AlexNet2.VGG3.GoogleNet4.ResNet5.MobileNet 1.AlexNet AlexNet是2012年ISLVRC 2012&#xff08;ImageNet Large Scale Visual Recognition Challenge&#xff09;竞赛的冠军网络。 首次利用 GPU 进行网络加速训练。使用了 ReLU 激活函数&#xff0c;而不是传统的 Si…...

Firebase Local Emulator Suite详解

文章目录 Firebase Local Emulator Suite 组件安装和使用步骤1. 安装 Firebase CLI2. 初始化 Firebase 项目3. 配置模拟器4. 启动模拟器5. 配置应用程序使用本地模拟器 常见用途 Firebase Local Emulator Suite 是一组本地服务&#xff0c;可以模拟 Firebase 平台的在线服务&am…...

计算机组成原理·存储系统疑点归纳

组原这门课有点学得不是很懂&#xff0c;现在快考试了&#xff0c;挑几个做错了的题分析、记录一下。 N o . 1 \mathit{No}.1 No.1  x x x、 y y y 为定点整数&#xff0c;其格式为 1 1 1 位符号位、 n n n 位数值位&#xff0c;若采用补码一位乘法实现乘法运算&#xff0c;则…...

在 GPU 上实现全规模文件系统加速

摘要 现代高性能计算和人工智能计算解决方案经常使用 GPU 作为其主要计算能力来源。这就为 GPU 应用程序的存储操作造成了严重的不平衡&#xff0c;因为每一个此类存储操作都必须向 CPU 发出信号并由 CPU 处理。在 GPU4FS 中&#xff0c;我们针对这种不平衡提出了一个彻底的解决…...

代码随想录算法训练营Day7|454.四数相加II、 383. 赎金信、15. 三数之和、 18. 四数之和

454.四数相加II 四个数组分成两组进行for循环&#xff0c;先用HashMap存储所有第一组for循环出现的和的次数。再进行第二组for循环&#xff0c;每一次得出的和判断其负数是否在map的key中&#xff0c;如果存在&#xff0c;就加上这个value。 class Solution {public int four…...

编译器屏障概述

文章目录 1. 前言2. 编译器内存屏障2.1 编译器内存访问重排序规则2.2 编译器屏障的几种形式2.2.1 显式编译器屏障2.2.2 隐式编译器屏障2.2.3 硬件内存屏障充当编译屏障2.2.4 编程语言内存模型提供的编译屏障 2.3 编译器内存屏障实例2.3.1 Linux spinlock 3. 结语4. 参考资料 1.…...

RUST宏编程入门

宏指示符 在Rust的宏编程中&#xff0c;宏可以接受多种类型的参数&#xff0c;称为“指示符”。这些指示符帮助宏识别不同类型的代码片段&#xff0c;并相应地处理它们。 这里列出全部指示符&#xff1a; blockexpr 用于表达式ident 用于变量名或函数名itemliteral 用于字面常…...

linux安装srs

获取srs cd /opt git clone -b 4.0release https://gitee.com/ossrs/srs.git cd srs/trunk 启动srs ./objs/srs -c conf/srs.conf ./etc/init.d/srs status 访问http://192.168.220.146:8080/出现下方图片说明安装成功 点击进入SRS控制台看到下方图片...

IO流(2)

缓冲流 字节缓冲流 利用字节缓冲区拷贝文件&#xff0c;一次读取一个字节&#xff1a; public class test {public static void main(String [] args) throws IOException {//利用字节缓冲区来拷贝文件BufferedInputStream bisnew BufferedInputStream(new FileInputStream(&…...

【docker】docker启动bitnami/mysql

说明&#xff1a;-v 宿主机目录:docker容器目录&#xff0c;-p 同理 注意&#xff1a;/opt/bitnami/mysql/conf/bitnami 目录自定义conf的目录&#xff0c;不能使用原有的/opt/bitnami/mysql/conf 目录。 容器启动后可在宿主机的/宿主/mysql8.0/conf&#xff0c;添加my_custom.…...

边缘计算、云计算、雾计算在物联网中的作用

边缘计算和雾计算不像云那样广为人知&#xff0c;但可以为企业和物联网公司提供很多帮助。这些网络解决了物联网云计算服务无法解决的许多问题&#xff0c;并使分散的数据存储适应特定的需求。让我们分别研究一下边缘计算、雾计算和云计算的优势。 雾计算的好处 低延迟。雾网络…...

【c语言】探索内存函数

探索内存函数 memcpy函数memmove函数memset函数memcmp函数&#xff1a; memcpy函数 memcpy函数声明&#xff1a; void * memcpy ( void * destination, const void * source, size_t num );将source空间下的num个字符复制到dest中去 函数的使用&#xff1a; 将字符数组a的5字…...

day46 完全背包理论基础 518. 零钱兑换 II 377. 组合总和 Ⅳ

完全背包理论基础 有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品都有无限个&#xff08;也就是可以放入背包多次&#xff09;&#xff0c;求解将哪些物品装入背包里物品价值总和最大。 01背包内嵌的循环是从…...

【linux】运维-基础知识-认知hahoop周边

1. HDFS HDFS&#xff08;Hadoop Distributed File System&#xff09;–Hadoop分布式文件存储系统 源自于Google的GFS论文&#xff0c;HDFS是GFS的克隆版 HDFS是Hadoop中数据存储和管理的基础 他是一个高容错的系统&#xff0c;能够自动解决硬件故障&#xff0c;eg&#xff1a…...

Python自动实时查询预约网站的剩余名额并在有余额时发邮件提示

本文介绍基于Python语言&#xff0c;自动、定时监测某体检预约网站中指定日期的体检余额&#xff0c;并在有体检余额时自动给自己发送邮件提醒的方法。 来到春招末期&#xff0c;很多单位进入了体检流程。其中&#xff0c;银行&#xff08;尤其是四大行&#xff09;喜欢“海检”…...

Flutter 验证码输入框

前言&#xff1a; 验证码输入框很常见&#xff1a;处理不好 bug也会比较多 想实现方法很多&#xff0c;这里列举一种完美方式&#xff0c;完美兼容 软键盘粘贴方式 效果如下&#xff1a; 之前使用 uniapp 的方式实现过一次 两种方式&#xff08;原理相同&#xff09;&#xff1…...

如何从0到设计一个CRM系统

什么是CRM 设计开始之前&#xff0c;先来了解一下什么是CRM。CRM&#xff08;Customer Relationship Management&#xff09;是指通过建立和维护与客户的良好关系&#xff0c;达到满足客户需求、提高客户满意度、增加业务收入的一种管理方法和策略。CRM涉及到跟踪和管理客户的所…...

Numba 的 CUDA 示例 (2/4):穿针引线

本教程为 Numba CUDA 示例 第 2 部分。 按照本系列从头开始使用 Python 学习 CUDA 编程 介绍 在本系列的第一部分中&#xff0c;我们讨论了如何使用 GPU 运行高度并行算法。高度并行任务是指任务完全相互独立的任务&#xff0c;例如对两个数组求和或应用任何元素函数。 在本教…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...