【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
,那么读端也会退出
四、命名管道和匿名管道的区别(特征)
命名管道的特征大致和匿名管道一样:
- 匿名管道和命名管道都是通过文件描述符进行通信的
- 无论是匿名管道还是命名管道,都是单向通信的,即数据只能从一端流向另一端。
- 面向字节流
- 进程是会协同的,同步与互斥的
不同点在于:
- 匿名管道通常用于有亲缘关系的进程之间的通信,比如父子进程;而命名管道可以用于没有亲缘关系的进程之间的通信,它是一种独立的通信方式。
- 匿名管道直接通过
pipe
函数创建使用,然后创建子进程进行通信;而命名管道需要先通过mkfifo
函数创建,然后再通过open
打开使用。 - 在匿名管道中,如果父进程创建多个子进程,会出现写端重复继承的情况,导致子进程之间也能互相通信;而命名管道不会出现这种情况。
五、 命名管道的四种情况
命名管道的四种情况和匿名管道的四种情况差不多,主要的区别在于第四点!
- 读写端正常,管道如果为空,读端就会被阻塞,等待写端的数据。
- 读写端正常,管道为满时,写端阻塞,等待读端读取数据。
- 读端正常读,写端关闭,那么读取端会在读取完管道中的所有数据后得到一个特殊的信号,表明已经到达了管道的末尾。这样读取操作就会返回值为
0
,也就是read
函数会返回0
,而不会再被阻塞(不会再等待管道中会有新的数据)。因此,当写端关闭后,读端就知道不会再有新的数据写入管道,可以安全地关闭管道,结束通信。
当我ctrl + c
终止了写端,对应读端也退出了
- 写端正常,读端关闭。写入操作不会因为读端关闭而阻塞,写入进程可以继续向管道写入数据,直到读取进程再次打开读端,或者管道被关闭,或者管道被写满。
这也是唯一和匿名管道的区别!对于匿名管道,写端正常,读端关闭,那么操作系统会为写端发送SIGPIPE
信号终止该进程。这是因为在匿名管道中,通信的两个进程是有血缘关系的,读取端关闭后,写入端无法将数据传递给任何进程,所以操作系统只能终止;而命名管道的任意进程之间都可以通信,所以写端只管写就行。
六、代码
Gitee
代码仓库:点击跳转
相关文章:
【Linux】进程间通信之命名管道
👦个人主页:Weraphael ✍🏻作者简介:目前正在学习c和算法 ✈️专栏:Linux 🐋 希望大家多多支持,咱一起进步!😁 如果文章有啥瑕疵,希望大佬指点一二 如果文章对…...
【内存管理】页表映射
页表的一些术语 现在Linux内核中支持四级页表的映射,我们先看下内核中关于页表的一些术语: 全局目录项,PGD(Page Global Directory) 上级目录项,PUD(Page Upper Directory) 中间目…...
Cloudpods 强大的多云管理平台部署
简介 Cloudpods 是一款简单、可靠的企业IaaS资源管理软件。帮助未云化企业全面云化IDC物理资源,提升企业IT管理效率。 Cloudpods 帮助客户在一个地方管理所有云计算资源。统一管理异构IT基础设施资源,极大简化多云架构复杂度和难度,帮助企业…...
深度学习的可微渲染
深度学习的可微渲染 可微渲染(Differentiable Rendering)是深度学习领域的一个重要概念,它将传统的计算机图形学与深度学习结合起来,通过使渲染过程可微分(differentiable),以便于在深度学习模…...
CAS Server Restful接口实现后台认证
背景 对于一些比较复杂定制化登录页的情况下,之前提到过可以自定义修改使用CAS Server提供的登录页这种操作已经明显跟不上复杂定制场景了,所以CAS Server也提供了支持Restful接口,支持服务端后台登陆,对于复杂登陆场景时&#x…...
Linux shell编程学习笔记58:cat /proc/mem 获取系统内存信息
0 前言 在开展系统安全检查的过程中,除了收集cpu信息,我们还需要收集内存信息。在Linux中,获取内存信息的命令很多,这里我们着重研究 cat /proc/mem命令。 1 cat /proc/mem命令 /proc/meminfo 文件提供了有关系统内存的使用情况…...
【InternLM实战营第二期笔记】07:OpenCompass :是骡子是马,拉出来溜溜
文章目录 课程实操 课程 评测的意义是什么呢?我最近也在想。看到这节开头的内容后忽然有个顿悟:如果大模型最终也会变成一种基础工具(类比软件),稳定或可预期的效果需要先于用户感知构建出来,评测 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:多项式求和 小K最近刚刚习得了一种非常酷炫的多项式求和技巧,可以对某几类特殊的多项式进行运算。非常不幸的是,小K发现老师在布置作业时抄错了数据,导致一道题并不能用刚学的方法来解,于是希望你能帮忙写一个程序…...
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.用循环的嵌套,输出输出如下图形 * * * * * * * * * * * * * * * * * * * * * * * * * 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】
状态更新计算过程: 计算卡尔曼增益: 根据预测的误差协方差矩阵 P k − P_k^- Pk− 和观测噪声协方差矩阵 R R R 计算卡尔曼增益 K k K_k Kk: 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} KkPk…...
计算引擎:Flink核心概念
Apache Flink 是一个流处理框架,擅长处理实时数据流和批处理任务。Flink 提供了强大的功能来处理和分析大量数据。以下是 Flink 的核心概念: 1. DataStream 和 DataSet API DataStream API: 用于处理无界数据流,即不断生成和流动的数据。例如,传感器数据、日志等。DataSet…...
技术前沿 |【大模型InstructBLIP进行指令微调】
大模型InstructBLIP进行指令微调 一、引言二、InstructBLIP模型介绍三、指令微调训练通用视觉语言模型的应用潜力四、InstructBLIP的指令微调训练步骤五、实验结果与讨论六、结论与展望 一、引言 随着人工智能技术的快速发展,视觉语言模型(Vision-Langu…...
CSS-布局-flex
CSS3 新增了弹性盒子模型( Flexible Box 或 FlexBox ),是一种新的用于在 HTML 页面实现布局的方式。使得 HTML 页面适应不同尺寸的屏幕和不同的设备时,元素是可预测地运行。 基本概念 容器:使用 display:flex 或 display:inline-flex 声明的…...
「C系列」C 数组
文章目录 一、C 数组1. 声明数组2. 初始化数组3. 访问数组元素4. 数组越界5. 多维数组 二、C 操作数组的方法有哪些三、C 数组-应用场景1. 存储固定数量的数据2. 实现算法(如排序)3. 处理数据集合 四、相关链接 一、C 数组 在C语言中,数组是…...
Python框架scrapy有什么天赋异禀
Scrapy框架与一般的爬虫代码之间有几个显著的区别,这些差异主要体现在设计模式、代码结构、执行效率以及可扩展性等方面。下面是一些关键的不同点: 结构化与模块化: Scrapy:提供了高度结构化的框架,包括定义好的Spider…...
【ROS2大白话】四、ROS2非常简单的传参方式
系列文章目录 【ROS2大白话】一、ROS2 humble及cartorgrapher安装 【ROS2大白话】二、turtlebot3安装 【ROS2大白话】三、给turtlebot3安装realsense深度相机 【ROS2大白话】四、ROS2非常简单的传参方式 文章目录 系列文章目录前言一、launch文件传参的demo1. 编写launch.py文…...
浅谈mysql 的批量delete 和 使用in条件批量删除问题
在考虑这两个DELETE语句的性能时,我们需要考虑数据库如何执行这些查询以及它们背后可能涉及的索引和数据结构。 1.执行多个单独的DELETE语句: DELETE FROM a WHERE b 1 AND c 1; ... DELETE FROM a WHERE b 1000 AND c 1000; 这种方法的优点是每…...
【Spring Boot】过滤敏感词的两种实现
文章目录 项目场景前置知识前缀树 实现方式解决方案一:读取敏感词文件生成前缀树构建敏感词过滤器1. 导入敏感词文件 src/main/resources/sensitive_words.txt2. 构建敏感词过滤器 SensitiveFilter3. 测试与使用 解决方案二:使用第三方插件 houbb/sensit…...
在 Zustand 中管理状态能使用类(Class)吗
在 Zustand 中,通常不推荐使用类(Class)来管理状态,因为 Zustand 的设计理念是基于函数式编程和 React Hooks 的。然而,仍然可以在 Zustand 中间接地使用类,但这并不是 Zustand 的典型用法。 如果确实想要…...
MoreTable 方法selectWithFun,count 使用实例
ORM Bee, example for MoreTable methods:selectWithFun,count ORM Bee时, MoreTable 方法selectWithFun,count 使用实例 package org.teasoft.exam.bee.osql;import org.teasoft.bee.osql.BeeException; import org.teasoft.bee.osql.FunctionType; import org.teasoft.be…...
【SpringBoot】在Spring中使用自定义条件类在Java声明Bean时实现条件注入
在Spring框架中,通过实现org.springframework.context.annotation.Condition接口并重写matches()方法,可以根据自定义条件来控制Bean的注入。这种机制非常灵活,可以帮助开发人员根据环境或配置来有选择地启用或禁用某些Bean。本文将详细介绍如…...
网卡聚合链路配置
创建名为mybond0的绑定,使用示例如下: # nmcli con add type bond con-name mybond0 ifname mybond0 mode active-backup添加从属接口,使用示例如下: # nmcli con add type bond-slave ifname enp3s0 master mybond0要添加其他从…...
PlantSimulation导入cad图作为背景
PlantSimulation导入cad图作为背景 首先要整理cad文件,正常的工艺规划总图中存在较多杂乱文件,这些信息是不需要的,如果直接导入,会非常卡。 1、打开cad软件,使用layon命令打开所有的隐藏图层,删除不需要…...
【大模型】个人对大模型选择的见解
选择大模型产品时,需要考虑多个因素,包括但不限于以下几点: 需求匹配度:首先,要明确你的需求是什么。不同的大模型产品可能在功能、性能、应用场景等方面有所侧重。例如,有的模型擅长自然语言处理ÿ…...
java的反射和python的鸭子类型
Java的反射(Reflection)和Python的鸭子类型(Duck Typing)感觉相似但又说不出具体的细节,本文借助kimi试图给出总结。 相似之处: 动态性:Java的反射允许程序在运行时查询、创建和修改类和对象的…...
爬虫工具yt-dlp
yt-dlp是youtube-dlp的一个fork,youtube-dlp曾经也较为活跃,但后来被众多网站屏蔽,于是大家转而在其基础上开发yt-dlp。yt-dlp的github项目地址为:GitHub - yt-dlp/yt-dlp: A feature-rich command-line audio/video downloaderA …...
【代码随想录训练营】【Day 50】【动态规划-9】| Leetcode 198, 213, 337
【代码随想录训练营】【Day 50】【动态规划-9】【需二刷】| Leetcode 198, 213, 337 需强化知识点 需二刷,打家劫舍系列 题目 198. 打家劫舍 class Solution:def rob(self, nums: List[int]) -> int:if len(nums) 1:return nums[0]dp [0] * (len(nums))dp…...
邯郸网站建设的地方/新手如何学seo
1、类SQL PLUS窗口:File->New->Command Window,这个类似于oracle的客户端工具sql plus,但比它好用多了。2、设置关键字自动大写:Tools->Preferences->Editor,将Keyword case选择Uppercase。这样在窗口中输入sql语句时,…...
百度如何给网站做评价/推广策略怎么写
523. 连续的子数组和 力扣类似这样的题目实在是不少, 子串使用前缀和的思想,为了记录,使用unordered_map。 class Solution { public:bool checkSubarraySum(vector<int>& a, int k) {if(k0){int t 0;for(int i0;i<a.size();i…...
微网站制作提供商推荐/广州seo服务外包
绝对定位与相对定位和浮动的区别与运用绝对定位使元素脱离文档流,因此不占据空间。普通文档流中元素的布局就当绝对定位的元素不存在时一样。因为绝对定位的框与文档流无关,所以它们可以覆盖页面上的其他元素。 而浮动元素的定位还是基于正常的文档流。C…...
网站建设288/广州seo关键词优化费用
atitit.设计模式(2) -----查表模式/ command 总结 1. 应用场景: 1 1. 取代一瓦if else 1 2. 建设api rpc风格的时候儿. 1 3. 菜单是Command模式的一个典型实例, 1 4. 上下文中执行客户代码 1 5. 使用命令模式作为"CallBack"在面向对象系统中的…...
采集电影做的网站/新闻联播今日新闻
点击右上方红色按钮关注“web秀”,让你真正秀起来前言vue组件非常常见的有父子组件通信,兄弟组件通信。而父子组件通信就很简单,父组件会通过 props 向下传数据给子组件,当子组件有事情要告诉父组件时会通过 $emit 事件告诉父组件…...
做网站找那些公司/常见的网络推广方法有哪些
前言 学习groovy的目的最终是为了更好的使用gradle,前面已经对groovy进行了一些列的学习,接下来开始gradle的学习。 一、Gradle的执行流程 1、Initialization初始化阶段 解析整个工程中的所有project,构建所有的Project对应的project对象…...