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

【Linux】进程间通信之命名管道

在这里插入图片描述

👦个人主页:Weraphael
✍🏻作者简介:目前正在学习c++和算法
✈️专栏:Linux
🐋 希望大家多多支持,咱一起进步!😁
如果文章有啥瑕疵,希望大佬指点一二
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注😍


目录

  • 一、见见猪跑
  • 二、命名管道的工作原理
  • 三、系统调用接口mkfifo
  • 四、命名管道和匿名管道的区别(特征)
  • 五、 命名管道的四种情况
  • 六、代码

一、见见猪跑

上篇我们学习到的匿名管道主要用于血缘关系的进程之间进行通信,而命名管道则可以在毫不相关的进程之间进行通信。命名管道是基于文件系统的,因此在使用命名管道进行通信时,需要遵循一定的权限规则和文件路径约定(原理部分会说)。

在命令行上使用mkfifo即可创建命名管道

mkfifo <filename>

mkfifo命令创建的命名管道在文件系统中显示为一种特殊的文件类型,通常以绿色文本显示,以便与普通文件区分开来。

请添加图片描述

创建命名管道后,进程可以像操作普通文件一样对其进行读取和写入操作。一个进程可以将数据写入管道,另一个进程可以从管道中读取数据。

在这里插入图片描述

如果可以看到,左端的echo是一个进程,右端的cat也是一个进程,它们两是毫无相关的,而通过命名管道,可以让这两个毫无相关的进程通信。

但需要注意的是,如果没有任何进程打开了管道进行读取操作,那么写入操作将永远被阻塞,直到有进程打开管道进行读取操作为止。这种行为确保了在进程之间进行通信时的同步性,即写入数据的进程会等待读取数据的进程准备好后再继续执行,从而避免了数据丢失或混乱。

二、命名管道的工作原理

请添加图片描述

我们知道:当进程打开文件时,操作系统会在内核中创建struct file结构体对象来描述这个被打开的文件。而一个进程可以打开多个文件,那进程结构体对象task_struct就要存储哪些文件是由哪一个进程打开的。因此,每个进程的task_struct对象都要和打开的文件建立关系!所以每个task_struct对象其实有一个指针struct files_struct* files,这个指针指向结构体files_struct,而这个结构体包含一个指针数组struct file* fd_array[],这个数组我们可以称之为文件描述符表。数组中的每个元素都是指向当前进程所打开文件的指针(地址)!

而如果两个不同的进程打开同一个文件,操作系统只会为这个打开的文件创建一个struct file结构体对象,只不过这个文件的结构体对象有一个引用计数(计数器)字段会是2,表示当前有两个进程打开此文件。

这意味着多个进程可以共享相同的文件资源(各自进程的文件描述表指向同一个文件结构体对象),这不就是进程间通信的本质:让不同的进程能共享同一份资源。一个进程可以向文件写入数据,而另一个进程则可以从文件中读取这些数据,从而实现了通信!

  • 而在上面我们看到当一个进程向管道文件写入数据时,另一个进程在查看该管道文件属性时,其文件大小却是0,但还是可以从该管道文件中获取数据现象。这是为什么?

其原因是:不管是匿名管道还是命名管道,写入数据的时候并不是将数据直接刷新到磁盘(访问磁盘有I/O效率问题)!而是存储在内核缓冲区中!因为操作系统管理着内核中每一个被打开的文件,那么操作系统就很清楚每一个被打开文件的类型。因此,如果操作系统识别是普通文件,那么就根据内核缓冲区的刷新策略,直接刷新到磁盘上;而如果识别到是管道文件,那么数据不会马上刷新到磁盘上,而是存储在内核缓冲区中,等待另外一个进程读取数据。因此命名管道(或匿名管道)通常被视为"内存级文件"。

  • 接下来还有一个边角问题:在匿名管道中,我们可以通过子进程通过继承父进程的文件描述符表,使得不同的进程可以打开同一个管道文件;那在命名管道中,我们怎么保证两个不同的进程打开的是同一个管道文件呢?

这就设计到【文件系统】的知识了,因为磁盘中一定会存在大量没有被打开的文件,那么就需要管理磁盘中每一个文件的属性,注定了存在大量的inode结构(文件属性的集合)。因此为了区分每个文件的inode结构,操作系统会为每个inode结构取一个唯一编号,即inode编号。所以,想要对文件操作,操作系统只认inode编号!但用户都是通过文件名来对文件操作的呀?这又是因为文件名和inode编号的关系是由目录来建立和维护的(目录文件的数据块存储着文件名和inode编号的映射关系)

因此,当不同进程通过需要通过同一个命名管道文件进行通信,必然要找到命名管道的文件路径,那么操作系统会根据文件名到指定的目录下的数据块中查找文件名映射的inode编号。因为inode编号是唯一的,从而可以确保这些进程打开的是同一个管道文件。

三、系统调用接口mkfifo

除了可以用makefifo命令来创建命名管道之外,还可以使用系统调用接口mkfifo函数来创建。

#include <sys/types.h>
#include <sys/stat.h>int mkfifo(const char *pathname, mode_t mode);

其中

  • pathname指定了要创建的命名管道的路径(包含文件名)

  • mode指定了创建出来管道文件的权限(类似于系统调用接口open函数的第三个参数)。

  • 返回值:

    • 成功创建命名管道时,mkfifo函数返回0

    • 失败则返回-1

代码样例思路:首先为了能让两个毫不相干的进程能够通信,创建两个源文件,分别是服务端server.cc和客户端client.cc。服务端主要是创建命名管道、读取管道数据和最后回收命名管道,而客户端主要是向管道中写入数据。

补充:.cc结尾的就是C++源文件的后缀名。常见后缀名有很多种,如.cpp.cc 或者 .cxx等,这取决于个人或团队的偏好。

  • comm.hpp:这个头文件主要是用来存放整个项目所需要的头文件以及自定义的错误码。

在这里插入图片描述

  • server.cc:创建命名管道、读取管道数据和最后回收命名管道。(详细内容可以看代码注释,非常详细!!!)

在这里插入图片描述

  • client.cc:向管道中写入数据。(详细内容可以看代码注释,非常详细!!!)

在这里插入图片描述

  • 程序演示

在这里插入图片描述

需要注意的是:

  • 必须要先运行sever端进程,因为要先将管道文件创建好后,才能开始通信。
  • 服务端启动后,因为是读端,所以会阻塞等待客户端(写端)写入数据,所以你会看到运行完服务端后,会有光标一直在闪烁。
  • 命名管道文件需要写端和读端都打开的时候才可以开始通信,否则只打开其中一个端会进入阻塞。我们可以理解为这是为了防止只打开读端而不打开写端,这是因为不打开写端,读端read函数就会返回0,那么读端也会退出

四、命名管道和匿名管道的区别(特征)

在这里插入图片描述

命名管道的特征大致和匿名管道一样:

  1. 匿名管道和命名管道都是通过文件描述符进行通信的
  2. 无论是匿名管道还是命名管道,都是单向通信的,即数据只能从一端流向另一端。
  3. 面向字节流
  4. 进程是会协同的,同步与互斥的

不同点在于:

  1. 匿名管道通常用于有亲缘关系的进程之间的通信,比如父子进程;而命名管道可以用于没有亲缘关系的进程之间的通信,它是一种独立的通信方式。
  2. 匿名管道直接通过pipe函数创建使用,然后创建子进程进行通信;而命名管道需要先通过mkfifo函数创建,然后再通过open打开使用。
  3. 在匿名管道中,如果父进程创建多个子进程,会出现写端重复继承的情况,导致子进程之间也能互相通信;而命名管道不会出现这种情况。

五、 命名管道的四种情况

命名管道的四种情况和匿名管道的四种情况差不多,主要的区别在于第四点!

  1. 读写端正常,管道如果为空,读端就会被阻塞,等待写端的数据。
  2. 读写端正常,管道为满时,写端阻塞,等待读端读取数据。
  3. 读端正常读,写端关闭,那么读取端会在读取完管道中的所有数据后得到一个特殊的信号,表明已经到达了管道的末尾。这样读取操作就会返回值为0,也就是read函数会返回0,而不会再被阻塞(不会再等待管道中会有新的数据)。因此,当写端关闭后,读端就知道不会再有新的数据写入管道,可以安全地关闭管道,结束通信。
    在这里插入图片描述
    当我ctrl + c终止了写端,对应读端也退出了
    在这里插入图片描述
  4. 写端正常,读端关闭。写入操作不会因为读端关闭而阻塞,写入进程可以继续向管道写入数据,直到读取进程再次打开读端,或者管道被关闭,或者管道被写满。
    在这里插入图片描述
    这也是唯一和匿名管道的区别!对于匿名管道,写端正常,读端关闭,那么操作系统会为写端发送SIGPIPE信号终止该进程。这是因为在匿名管道中,通信的两个进程是有血缘关系的,读取端关闭后,写入端无法将数据传递给任何进程,所以操作系统只能终止;而命名管道的任意进程之间都可以通信,所以写端只管写就行。

六、代码

Gitee代码仓库:点击跳转

相关文章:

【Linux】进程间通信之命名管道

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…...

【内存管理】页表映射

页表的一些术语 现在Linux内核中支持四级页表的映射&#xff0c;我们先看下内核中关于页表的一些术语&#xff1a; 全局目录项&#xff0c;PGD&#xff08;Page Global Directory&#xff09; 上级目录项&#xff0c;PUD&#xff08;Page Upper Directory&#xff09; 中间目…...

Cloudpods 强大的多云管理平台部署

简介 Cloudpods 是一款简单、可靠的企业IaaS资源管理软件。帮助未云化企业全面云化IDC物理资源&#xff0c;提升企业IT管理效率。 Cloudpods 帮助客户在一个地方管理所有云计算资源。统一管理异构IT基础设施资源&#xff0c;极大简化多云架构复杂度和难度&#xff0c;帮助企业…...

深度学习的可微渲染

深度学习的可微渲染 可微渲染&#xff08;Differentiable Rendering&#xff09;是深度学习领域的一个重要概念&#xff0c;它将传统的计算机图形学与深度学习结合起来&#xff0c;通过使渲染过程可微分&#xff08;differentiable&#xff09;&#xff0c;以便于在深度学习模…...

CAS Server Restful接口实现后台认证

背景 对于一些比较复杂定制化登录页的情况下&#xff0c;之前提到过可以自定义修改使用CAS Server提供的登录页这种操作已经明显跟不上复杂定制场景了&#xff0c;所以CAS Server也提供了支持Restful接口&#xff0c;支持服务端后台登陆&#xff0c;对于复杂登陆场景时&#x…...

Linux shell编程学习笔记58:cat /proc/mem 获取系统内存信息

0 前言 在开展系统安全检查的过程中&#xff0c;除了收集cpu信息&#xff0c;我们还需要收集内存信息。在Linux中&#xff0c;获取内存信息的命令很多&#xff0c;这里我们着重研究 cat /proc/mem命令。 1 cat /proc/mem命令 /proc/meminfo 文件提供了有关系统内存的使用情况…...

【InternLM实战营第二期笔记】07:OpenCompass :是骡子是马,拉出来溜溜

文章目录 课程实操 课程 评测的意义是什么呢&#xff1f;我最近也在想。看到这节开头的内容后忽然有个顿悟&#xff1a;如果大模型最终也会变成一种基础工具&#xff08;类比软件&#xff09;&#xff0c;稳定或可预期的效果需要先于用户感知构建出来&#xff0c;评测 case 就…...

matlab演示银河系转动动画

代码 function GalaxyRotationSimulation()% 参数设置num_stars 1000; % 恒星数量galaxy_radius 1; % 银河系半径rotation_speed 0.05; % 旋转速度% 生成银河系中的恒星分布theta 2 * pi * rand(num_stars, 1); % 角度r galaxy_radius * sqrt(rand(num_stars, 1)); % 半径…...

备战 清华大学 上机编程考试-冲刺前50%,倒数第5天

T1&#xff1a;多项式求和 小K最近刚刚习得了一种非常酷炫的多项式求和技巧&#xff0c;可以对某几类特殊的多项式进行运算。非常不幸的是&#xff0c;小K发现老师在布置作业时抄错了数据&#xff0c;导致一道题并不能用刚学的方法来解&#xff0c;于是希望你能帮忙写一个程序…...

leetCode127. 单词接龙

leetCode127. 单词接龙 // bfs 剪枝 class Solution { public:int ladderLength(string beginWord, string endWord, vector<string>& wordList) {// 1.将所有的单词放在set字段中unordered_set<string> s;for (auto & ele : wordList) s.insert(ele);//…...

进程概念(二)

目录 进程优先级基本概念查看系统进程PRI and NIPRI vs NI修改进程优先级的命令renice修改优先级进程其他概念 环境变量基本概念查看环境变量方法常见环境变量PATHHOMESHELL 查看环境变量环境变量相关的命令 环境变量特征命令行参数main函数中的俩个参数 argc argvmain函数的第…...

java程序100道01—20

1&#xff0e;用循环的嵌套&#xff0c;输出输出如下图形 * * * * * * * * * * * * * * * * * * * * * * * * * package Exercises.One_Hundred; ​ public class Demo01 {public static void main(String[] args) {for(int i1;i<5;i){for(int j1;j<2*i-1;j){Sys…...

让GNSSRTK不再难【第二天-第7部分2】

状态更新计算过程&#xff1a; 计算卡尔曼增益&#xff1a; 根据预测的误差协方差矩阵 P k − P_k^- Pk−​ 和观测噪声协方差矩阵 R R R 计算卡尔曼增益 K k K_k Kk​&#xff1a; K k P k − H T ( H P k − H T R ) − 1 K_k P_k^- H^T (H P_k^- H^T R)^{-1} Kk​Pk…...

计算引擎:Flink核心概念

Apache Flink 是一个流处理框架,擅长处理实时数据流和批处理任务。Flink 提供了强大的功能来处理和分析大量数据。以下是 Flink 的核心概念: 1. DataStream 和 DataSet API DataStream API: 用于处理无界数据流,即不断生成和流动的数据。例如,传感器数据、日志等。DataSet…...

技术前沿 |【大模型InstructBLIP进行指令微调】

大模型InstructBLIP进行指令微调 一、引言二、InstructBLIP模型介绍三、指令微调训练通用视觉语言模型的应用潜力四、InstructBLIP的指令微调训练步骤五、实验结果与讨论六、结论与展望 一、引言 随着人工智能技术的快速发展&#xff0c;视觉语言模型&#xff08;Vision-Langu…...

CSS-布局-flex

CSS3 新增了弹性盒子模型( Flexible Box 或 FlexBox )&#xff0c;是一种新的用于在 HTML 页面实现布局的方式。使得 HTML 页面适应不同尺寸的屏幕和不同的设备时&#xff0c;元素是可预测地运行。 基本概念 容器&#xff1a;使用 display:flex 或 display:inline-flex 声明的…...

「C系列」C 数组

文章目录 一、C 数组1. 声明数组2. 初始化数组3. 访问数组元素4. 数组越界5. 多维数组 二、C 操作数组的方法有哪些三、C 数组-应用场景1. 存储固定数量的数据2. 实现算法&#xff08;如排序&#xff09;3. 处理数据集合 四、相关链接 一、C 数组 在C语言中&#xff0c;数组是…...

Python框架scrapy有什么天赋异禀

Scrapy框架与一般的爬虫代码之间有几个显著的区别&#xff0c;这些差异主要体现在设计模式、代码结构、执行效率以及可扩展性等方面。下面是一些关键的不同点&#xff1a; 结构化与模块化&#xff1a; Scrapy&#xff1a;提供了高度结构化的框架&#xff0c;包括定义好的Spider…...

【ROS2大白话】四、ROS2非常简单的传参方式

系列文章目录 【ROS2大白话】一、ROS2 humble及cartorgrapher安装 【ROS2大白话】二、turtlebot3安装 【ROS2大白话】三、给turtlebot3安装realsense深度相机 【ROS2大白话】四、ROS2非常简单的传参方式 文章目录 系列文章目录前言一、launch文件传参的demo1. 编写launch.py文…...

浅谈mysql 的批量delete 和 使用in条件批量删除问题

在考虑这两个DELETE语句的性能时&#xff0c;我们需要考虑数据库如何执行这些查询以及它们背后可能涉及的索引和数据结构。 1.执行多个单独的DELETE语句&#xff1a; DELETE FROM a WHERE b 1 AND c 1; ... DELETE FROM a WHERE b 1000 AND c 1000; 这种方法的优点是每…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架&#xff0c;用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录&#xff0c;以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

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

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

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...