Linux--进程间通信之命名管道

在这里插入图片描述


目录

  • 前言
  • 概念
    • 命名管道的创建
    • 命名管道特性
  • 命名管道通信
    • 建立连接
    • 资源处理
  • Client && Server通信
  • 总结


前言

上一篇文章介绍匿名管道的进程间通信只适合在具有血缘关系的进程间进行通信,但是如果我们想让两个不相关的进程实现通信,使用匿名管道显然已经不太合适,这时候就可以使用另一种方案来实现让不同的进程间进行通信,这就是这篇文章要介绍的——命名管道。

概念

命名管道(Named Pipes),也称为FIFO(First In, First Out),是一种进程间通信的机制。它允许不相关的进程在一个系统中通过文件系统来进行通信。

在这里插入图片描述

命名管道的创建

命名管道的创建可以使用命令行工具(如mkfifo命令)或者在编程语言中的调用系统调用接口(如mkfifo函数)来创建命名管道。与匿名管道一样,命名管道也存在于内存中,命名管道是一种特殊类型的文件,类似于普通管道。数据通过命名管道传输时不会写入磁盘,而是在内存中进行传递。命名管道允许多个进程通过使用相同的管道名称进行通信,而不仅仅是两个进程之间的通信。与普通管道一样,命名管道中的数据也是临时存储在内存中的。

在命令行中可以直接使用命令mkfifo [pipename]来创建我们需要的命名管道文件。

在这里插入图片描述
或者可以使用系统调用接口int mkfifo(const char *pathname, mode_t mode)来创建所需要的管道文件,如下代码。

#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
int main()
{umask(0);int ret = mkfifo("namepipe", 0666);if (ret == -1){std::cout << errno << " : " << strerror(errno) << std::endl;}else{std::cout << "create success!" << std::endl;}return 0;
}

因为命名管道在创建后也是一种文件,所以在使用mkfifo系统调用接口时需要注意给定权限。文件最终的权限为mode & ~umask,因此在创建之前我们可以先将umask置0。另外使用mkfifo创建命名管道如果成功则返回0,失败返回-1并设置错误码,所以在创建时可以接收返回值做差错处理。

在这里插入图片描述

命名管道特性

命名管道与匿名管道类似,允许两个或多个进程通过读取和写入管道文件来进行通信。一个进程可以将数据写入管道,而另一个进程可以从管道中读取这些数据。也是一种半双工通信,数据按照写入的顺序以字节流的形式读取。如果没有进程打开管道的另一端进行读取,写入进程可能会被阻塞,直到有其他进程来读取数据。同样,如果没有进程写入管道,尝试读取管道的进程也会被阻塞。命名管道的声明周期是持久的,直到被明确删除为止。命名管道不适用于网络通信,它仅用于本地进程之间的通信。

命名管道通信

建立连接

使用命名管道通信前提还是让相互独立的进程能看到同一份资源,对同一份资源进行操作。所以在命名管道通信之前要先建立链接,建立链接第一步就是创建命名管道,然后在打开命名管道。为了能让不同进程能对同一个管道文件进行操作,因此应该约定好让一个进程在某个路径下创建好一个命名管道,其余进程就可以直接打开这个路径下的命名管道,这样就可以让几个进程先建立好链接。

资源处理

因为命名管道生命周期不随进程,一旦创建后如果不是人为删除就会一直存在,因此在通信完毕之后除了关闭相应的文件描述符,还需要将没有用的管道文件进行删除。在命令行上可以使用rm命令,在程序里面可以使用unlink系统调用接口函数进行删除。

  • unlink是一个系统调用函数,用于删除文件系统中的文件。它可以删除普通文件、符号链接和命名管道等文件类型。
  • 当你调用unlink函数来删除一个文件时,它会从文件系统中删除该文件的目录项(directory entry),并释放该文件占用的磁盘空间。文件的实际数据在删除后将不再可用。但是,如果有其他进程仍然打开了该文件,那么文件仍然存在,只是无法通过文件名访问。只有当所有对该文件的打开引用都关闭后,文件空间才会被完全释放。
  • 需要注意的是,unlink函数只删除文件的目录项,而不会对打开的文件描述符产生影响。这意味着,即使使用unlink删除了文件,仍然可以通过已打开的文件描述符继续访问和操作文件的内容,直到关闭文件描述符。使用unlink函数删除文件是一个不可逆的操作,请谨慎使用,确保你真正想要删除的是该文件。

在这里插入图片描述

Client && Server通信

万事俱备,只欠东风。在有了上述的内容储备后,就可以简单的写一份Client和Server两进程的简单通信了。

可以设计一个这样的程序,让Server进程创建一个命名管道,并以只读的方式打开,然后循环的读取内容。让Client进程直接以只写的方式打开命名管道,循环的将数据写入到命名管道中。当Server进程检测到Client进程退出时,Server进程关闭相应的文件描述符并删除命名管道。为了更好的测试,可以将程序设计为交互式的,当我们输入quit时Client结束写入跳出循环然后关闭文件描述符退出,Server进程在检测到Client进程退出后,再将管道里数据读取完毕后也跳出循环结束读取,关闭文件描述符后删除命名管道。这样我们就可以写出如下代码:

//comm.hpp
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <cstring>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#define NUM 1024mode_t mode = 0666;
const std::string fileName = "./fifo";
//Server.cc
#include "comm.hpp"int main()
{umask(0);// 创建命名管道int ret = mkfifo(fileName.c_str(), mode);if (ret == -1){std::cout << errno << " : " << strerror(errno) << std::endl;exit(-1);}std::cout << "create namepipe success" << std::endl;// 打开命名管道int fd = open(fileName.c_str(), O_RDONLY);if (fd < 0){std::cout << errno << " : " << strerror(errno) << std::endl;exit(-1);}// 开始写入while (1){char buffer[NUM];int n = read(fd, buffer, sizeof(buffer));if (n > 0){buffer[n] = '\0';std::cout << "client # " << buffer << std::endl;}else if (n == 0){std::cout << "communication finish" << std::endl;break;}else{std::cout << errno << " : " << strerror(errno) << std::endl;break;}}close(fd);unlink(fileName.c_str());return 0;
}
//Client.cc
#include "comm.hpp"
#include <iostream>
bool check(const char* s)
{std::string str;while(*s != '\n'){str += *s;s++;}return str != "quit";
}int main()
{// 打开命名管道int fd = open(fileName.c_str(), O_WRONLY);if (fd < 0){std::cout << errno << " : " << strerror(errno) << std::endl;exit(-1);}// 写入内容char buffer[NUM];std::cout << "Input : ";char* ret = fgets(buffer, NUM, stdin);while (check(ret)){buffer[strlen(buffer) - 1] = '\0';write(fd, buffer, strlen(buffer));std::cout << "Input : ";ret = fgets(buffer, NUM, stdin);}close(fd);return 0;
}

在这里插入图片描述

总结

管道是一种在进程间进行通信的机制。它可以用于在一个进程中将输出连接到另一个进程的输入,从而实现它们之间的数据传输。无论是命名管道还是匿名管道,他们都属于管道通信并且都具有如下的几种特性:

  • 单向通信:管道是单向的,分为读端和写端。写入端将数据写入管道,读取端从管道中读取数据。数据在管道中按先进先出(FIFO)的顺序传输。

  • 匿名管道和命名管道:管道可以是匿名的,也可以是命名的。匿名管道只能在具有亲缘关系的进程之间使用,而命名管道可以用于无关进程之间的通信。

  • 进程间通信:管道通信通常用于父子进程或者兄弟进程之间的通信。父进程创建管道,并将其的写端传递给子进程,子进程通过读取管道来接收父进程发送的数据。

  • 有限的容量:管道有一个有限的容量,通常是操作系统内核中的一个缓冲区。一旦管道被填满,进一步的写入操作将会阻塞,直到有足够的空间来容纳数据。

  • 阻塞和非阻塞操作:管道的读取和写入操作可以是阻塞的或非阻塞的。阻塞操作将会一直等待直到数据可用或空间可用,而非阻塞操作将立即返回,无论是否有数据可用或空间可用。

  • 临时性:管道中的数据是临时的,一旦相关进程关闭了管道的读写端,管道中的数据将被销毁,无法再被读取。这是因为管道的数据存储在内核的缓冲区中,而不是保存在文件系统中。

管道是一种简单而有效的进程间通信机制,但它也有一些限制。例如,它只支持单向通信,数据传输是基于字节流而不是消息的,且容量有限。如果需要更复杂的通信需求,可以考虑其他的进程间通信方式,如命名管道、消息队列、共享内存等。

最后,码文不易,如果觉得文章对你有帮助的话,就点一个👍呗。

在这里插入图片描述

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

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

相关文章

某企查ymg_ssr列表详情

js篇— 今天来看下某企查的列表详情–侵删 header发现这个参数 先断点一下 然后上一步 就到了这个地方 就开始扣一下这个js 三大段&#xff0c;先不解混淆了&#xff0c; 给a粘贴出来 &#xff0c;去掉自执行 给结果稍微改一下 缺windows&#xff0c;开始补环境 直接上…

Linux常见指令(1)

Linux常见指令[1] 一.前言1.操作系统简述 二.Linux常见指令1.登录Xshell2.Linux下的常见命令1.pwd2.ls1.ls -a2.ls -d3.ls -l 3.cd Linux中的文件系统1.文件的相关知识2.Linux下目录结构的认识1.什么叫做路径?2.Linux的整体目录结构3.为什么要有路径呢?4.绝对路径与相对路径 …

常识判断 --- 科技常识

目录 力与热 光和声 航空成就 垃圾分类 百科知识 血型 二十四节气歌 春雨惊春清谷天 夏满忙夏暑相连 秋处露秋寒霜降 冬雪雪冬小大寒 力与热 光和声 航空成就 垃圾分类 百科知识 血型

ThemeForest – Canvas 7.2.0 – 多用途 HTML5 模板

ThemeForest 上的 HTML 网站模板受到全球数百万客户的喜爱。与包含网站所有页面并允许您在 WP 仪表板中自定义字体和样式的 WordPress 主题不同&#xff0c;这些设计模板是用 HTML 构建的。您可以在 HTML 编辑器中编辑模板&#xff0c;但不能在 WordPress 上编辑模板&#xff0…

35 LRU缓存

LRU缓存 题解1 双map&#xff08;差2个testcases&#xff09;题解2 哈希表双向链表&#xff08;参考&#xff09;题解3 STL:listunordered_map 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正…

SpringMVC+统一表现层返回值+异常处理器

一、统一表现层返回值 根据我们不同的处理方法&#xff0c;返回的数据格式都会不同&#xff0c;例如添加只返回true|false&#xff0c;删除同理&#xff0c;而查询却返回数据。 Result类 为此我们封装一个result类来用于表现层的返回。 public class Result {//描述统一格式…

国庆中秋喜相逢

鲁迅先生曾经说过&#xff0c;“一个国家的文学&#xff0c;就是那个民族心灵的缩影。”在这个充满着诗与远方的中秋佳节&#xff0c;我们迎来了又一个国庆节&#xff0c;不由自主地感慨起这个祖国的壮美与辉煌。 中秋节&#xff0c;是中华民族传统的佳节之一&#xff0c;也是…

关于:Java8新特性函数式编程 - Lambda、Stream流、Optional

函数式编程 stream流 1.常用方法 1.1中间操作 filter ​ 可以对流中的元素进行条件过滤&#xff0c;符合过滤条件的才能继续留在流中 例如&#xff0c;打印所有姓名长度大于1的作家的姓名 List<Author> authors getAuthors(); authors.stream().filter(author -&g…

publicPath:打包时的配置

vue项目&#xff0c;执行打包命令后&#xff0c;会在项目的根目录中自动创建一个文件夹dist,dist中的文件就是打包后的文件&#xff0c;只需要放到服务器中即可。 【默认情况下&#xff0c;用的绝对路径&#xff0c;需要放到服务器的根目录打开。】 如果希望放到子目录也能运行…

背靠背 HVDC-MMC模块化多电平转换器输电系统-用于无源网络系统的电能质量调节MATLAB仿真模型

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; MATLAB2021版本 模型简介&#xff1a; MMC-HVDC模拟背靠背HVDC模块化多电平换流器&#xff08;MMC&#xff09;作为为整个电网供电的电能质量调节系统。因此&#xff0c;模块化多电平逆变器作为远程端转换器…

前端判断: []+[], []+{}, {}+[], {}+{}

本质: 二元操作符规则 一般判断规则: 如果操作数是对象,则对象会转换为原始值如果其中一个操作数是字符串的话,另一个操作数也会转换成字符串,进行字符串拼接否则,两个操作数都将转换成数字或NaN,进行加法操作 转为原始数据类型的值的方法: Symbol.ToPrimitiveObject.protot…

C#并发编程的实现方式

一、多线程&#xff1a;是一种并发编程技术&#xff0c;它允许一个应用程序同时执行多个线程。每个线程都有自己的指令集和堆栈&#xff0c;可以在不同的CPU核心上并行运行&#xff0c;或者在一个CPU核心上通过时间片轮转的方式交替运行。多线程的主要优点是可以利用多核处理器…

八、3d场景的区域光墙

在遇到区域展示的时候我们就能看到炫酷的区域选中效果&#xff0c;那么代码是怎么编辑的呢&#xff0c;今天咱们就好好说说&#xff0c;下面看实现效果。 思路&#xff1a; 首先&#xff0c;光墙肯定有多个&#xff0c;那么必须要创建一个新的js文件来作为他的原型对象。这个光…

SolidWorks 入门笔记03:生成工程图和一键标注

默认情况下&#xff0c;SOLIDWORKS系统在工程图和零件或装配体三维模型之间提供全相关的功能&#xff0c;全相关意味着无论什么时候修改零件或装配体的三维模型&#xff0c;所有相关的工程视图将自动更新&#xff0c;以反映零件或装配体的形状和尺寸变化&#xff1b;反之&#…

NOSQL Redis 数据持久化

Redis 数据持久化 快照方式&#xff08;RDB&#xff0c;Redis DataBase&#xff09; 全量的 在指定的时间间隔能对你的数据进行快照存储。文件追加方式&#xff08;AOF&#xff0c;Append only File&#xff09;增量 记录每次对服务器写的操作,当服务器重启的时候会重新执行这…

时间管理器:高效管理你的时间

随着社会的发展和生活节奏的加快&#xff0c;时间管理成为了人们日常生活中不可或缺的一部分。每个人都希望能够高效利用时间&#xff0c;提高工作和生活的效率。然而&#xff0c;在忙碌的生活中&#xff0c;很多人常常感到无所适从、无法合理规划自己的时间。这时&#xff0c;…

Flutter:类功能索引(全)

Flutter 类功能索引&#xff08;全&#xff09; 本文以表描述形式收录了Flutter中提供的各个类&#xff0c;旨在方便地进行查询相关组件。 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/133415589 跳转&#xff1a;字母索引 A 组件名称描述Animat…

linux centos7 安装mongodb7.0.1 及 mongosh2.0.1

下载数据库并解压 wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-7.0.1.tgz tar -zxf mongodb-linux-x86_64-rhel70-7.0.1.tgz #移动到/usr/local/mongo目录 mv mongodb-linux-x86_64-rhel70-7.0.1 /usr/local/mongodbmongosh 命令行下载 #下载命令行…

毕业设计选题之Java+springboot线上蔬菜销售与配送系统(源码+调试+开题+lw)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人七年开发经验&#xff0c;擅长Java、Python、PHP、.NET、微信小程序、爬虫、大数据等&#xff0c;大家有这一块的问题可以一起交流&#xff01; &#x1f495;&…

qml保姆级教程一:布局组件

&#x1f482; 个人主页:pp不会算法v &#x1f91f; 版权: 本文由【pp不会算法v】原创、在CSDN首发、需要转载请联系博主 &#x1f4ac; 如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连)和订阅专栏哦 QML系列教程 QML教程一&#xff1a;布局组件 文章目录 锚布局anchors属…