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

无名管道 / 有名管道(FIFO)

根据上节所讲就可以了解到:管道其实就是实现进程间通讯IPC中的一种类型方法

基本概念(无名管道)

管道是一种最基本的IPC机制,通常指无名管道,也是UNIX系统IPC最古老的形式。管道只能作用于有血缘关系的进程之间,完成数据传递。调用pipe系统函数即可创建一个管道。有如下特质:

  1. 其本质是一个伪文件(实为内核缓冲区),可以使用普通的read,write等函数进行读写
  2. 由两个文件描述符引用,一个表示读端,一个表示写端
  3. 规定数据从管道的写端流入管道,从读端流出

管道的原理

管道实为内核使用环形队列机制,借助内核缓冲区(4k)实现。

管道的局限性

  • 数据一旦被读走,便不在管道中存在,不可反复读取
  • 由于管道采用半双工通信方式。因此,数据只能在一个方向上流动

所谓半双工,其实在讲串口的时候就提到过,也就是同一时间要么只能写要么只能读,不能同时写和读。 对于进程通讯就是:父进程写的时候子进程只能读;子进程写的时候父进程只能读。

  • 只能在有公共祖先的进程间使用管道

( 常见的通信方式有,单工通信、半双工通信、全双工通信 

pipe函数(无名管道)

当成功调用pipe函数时,会创建两个文件描述符,fd[0] -> 读(r)fd[1]-> 写(w)之后如果想要向管道写数据就往fd[1]里面写,如果想从管道读数据就从fd[0]里面读!

如果要关闭管道,只需要关闭这两个文件描述符就可以了。

需要添加的库

 #include <unistd.h>

函数原型

int pipe(int pipefd[2]);

函数参数

  • pipefd[2]:表示一个包含两个文件描述符的数组,也就是上面提到分别代表读和写的 fd[0] 和 fd[1]
  • 返回值:若成功返回0,失败则返回-1

实操演示

创建一个名为'IPC"的文件夹,关于各种IPC的学习代码都放在这个文件夹下:

注意,由于fork函数会拷贝一份一样的程序给子进程,所以管道的创建应该在fork之前,这样父子进程就都有了fd[0]和fd[1],并且由于管道指向内核,所以父子进程的fd[0]和fd[1]是相同的。

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>int main()
{int fd[2];pid_t fork_return;char *writebuf = "mjmmjmmm";char readbuf[1024] = {0};if(pipe(fd) == -1){printf("pipe error\n");}fork_return = fork();if(fork_return > 0){//fatherclose(fd[0]);//ssize_t write(int fd, const void *buf, size_t count);write(fd[1],writebuf,strlen(writebuf));wait(NULL);}else if(fork_return == -1){//errorprintf("fork error\n");}else{//sonclose(fd[1]);//ssize_t read(int fd, void *buf, size_t count);read(fd[0],&readbuf,1024);printf("read from pipe:%s\n",readbuf);exit(1);}return 0;
}

实现效果

基本概念(有名管道)

FIFO,也称为命名管道,它是一种文件类型。

有名管道的特点

  • FIFO可以在无关的进程之间交换数据,与无名管道不同
  • FIFO有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中

mkfifo函数(有名管道) 

需要添加的库

#include <sys/stat.h>

函数原型

int mkfifo(const char *pathname, mode_t mode);

函数参数

  • pathname:文件路径
  • mode:mode 参数与open函数中的 mode 相同。一旦创建了一个 FIFO,就可以用一般的文件I/O函数操作它

关于open函数中的mode:

其中较为常用的是:

  • S_IRWXU:对主用户来说可读,可写,可执行
  • S_IRUSR:对主用户来说可读
  • S_IWUSR:对主用户来说可写
  • S_IXUSR:对主用户来说可执行

详见:Linux 系统编程 开篇/ 文件的打开/创建_mjmmm的博客-CSDN博客

  • 返回值:成功返回0,出错返回-1

既然可以用一般文件的I/O函数操作它,就意味可以使用open来打开,而open中的第二个参数flag中有一个选项是“O_NONBLOCK”,这是非阻塞标志

  • 若没有指定O_NONBLOCK(默认),只读 open 要阻塞到某个其他进程为写而打开此 FIFO。类似的,只写 open 要阻塞到某个其他进程为读而打开它

  • 若指定了O_NONBLOCK,则只读 open 立即返回。而只写 open 将出错返回 -1 如果没有进程已经为读而打开该 FIFO,其errno置ENXIO。

参考:进程间通信(一)管道的pipe函数 FIFO的mkfifo函数_mkfifo 多进程_点灯小哥的博客-CSDN博客

实操演示

FIFO的通讯方式类似于在进程中使用文件来传输数据,只不过FIFO类型文件同时具有管道的特性。在数据读出时,FIFO管道中同时清除数据,并且“先进先出”

fifo1.c:(只读open FIFO,并不设“O_NONBLOCK”

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>int main()
{if(mkfifo("./fifo",S_IRWXU) == -1 && errno != EEXIST) //如果创建失败 且 没有已存在的FIFO{printf("mkfifo failed\n");perror("why");}int fd = open("./fifo",O_RDONLY); //only readprintf("open success\n");return 0;
}

实现效果1:

可见,由于没有设置O_NONBLOCK,且没有进程只写打开FIFO,所以只读打开FIFO会一直阻塞

fifo2.c:(只读open FIFO,并设置“O_NONBLOCK”

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>int main()
{if(mkfifo("./fifo",S_IRWXU) == -1 && errno != EEXIST){printf("mkfifo failed\n");perror("why");}int fd = open("./fifo",O_RDONLY|O_NONBLOCK); //only readprintf("open success\n");return 0;
}

实现效果2:

 

可见,由于加上了O_NONBLOCK,虽然没有进程只写打开FIFO,但是只读打开不会阻塞而是立刻返回,并执行了printf 

fifo3.c & fifo4.c:(创建两个进程,fifo3一直写,fifo4一直读)

fifio3.c:(一直写)
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>int main()
{char *str = "mjmmmmjjm";int fd = open("./fifo",O_WRONLY); //only writeprintf("open success\n");while(1){write(fd,str,strlen(str));sleep(1);}close(fd);return 0;
}
fifo4.c:(一直读)
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>int main()
{char buf[30] = {0};int nread = 0;if(mkfifo("./fifo",S_IRWXU) == -1 && errno != EEXIST){printf("mkfifo failed\n");perror("why");}int fd = open("./fifo",O_RDONLY); //only readprintf("read open success\n");while(1){read(fd,&buf,30);printf("read %d byte from fifo,context: %s\n",nread,buf);}close(fd);return 0;
}

实现效果3:

先编译并运行fifo4.c:

可见没有进程只写打开FIFO,所以一直阻塞

然后再新的窗口编译并运行fifo3.c:

此时有进程只写打开FIFO并每隔一秒向其中写入数据

此时再观察fifo4.c的输出:

 

此时只读FIFO不再阻塞,并每隔一秒读到只写FIFO写入的数据! 

上述例子可以扩展成 客户进程—服务器进程 通信的实例负责写的fifo3.c的作用类似于客户端,可以打开多个客户端向一个服务器发送请求信息,负责读的fifo4.c类似于服务器,它适时监控着FIFO的读端,当有数据时,读出并进行处理,但是有一个关键的问题是,每一个客户端必须预先知道服务器提供的FIFO接口,下图显示了这种安排:

 

相关文章:

无名管道 / 有名管道(FIFO)

根据上节所讲就可以了解到&#xff1a;管道其实就是实现进程间通讯IPC中的一种类型方法 基本概念&#xff08;无名管道&#xff09; 管道是一种最基本的IPC机制&#xff0c;通常指无名管道&#xff0c;也是UNIX系统IPC最古老的形式。管道只能作用于有血缘关系的进程之间&…...

Three.js纹理贴图

目录 Three.js入门 Three.js光源 Three.js阴影 Three.js纹理贴图 纹理是一种图像或图像数据&#xff0c;用于为物体的材质提供颜色、纹理、法线、位移等信息&#xff0c;从而实现更加逼真的渲染结果。 纹理可以应用于Three.js中的材质类型&#xff0c;如MeshBasicMaterial…...

1+X Web前端开发职业技能等级证书建设方案

一 、系统概述 1X Web前端开发技术是计算机类专业重要的核心课程&#xff0c;课程所包含的教学内容多&#xff0c;实践性强&#xff0c;并且相关技术更新快。传统的课堂讲授模式以教师为中心&#xff0c;学生被动式接收&#xff0c;难以调动学生学习的积极性和主动性。混合式教…...

Rx.NET in Action 第二章学习笔记

2 Hello, Rx 本章节涵盖的内容: 不使用Rx的工作方式向项目中添加Rx创建你的第一个Rx应用程序 Rx 的目标是协调和统筹来自社交网络、传感器、用户界面事件等不同来源的基于事件的异步计算。例如&#xff0c;建筑物周围的监控摄像头和移动传感器会在有人靠近建筑物时触发&#xf…...

【软件工程 | 模块耦合】什么是模块耦合及分类

概念 耦合(coupling)是对两个模块之间联接程度的一种度量。模块间的依赖程度越大&#xff0c;则其耦合程度也就越大&#xff1b; 反之&#xff0c;模块间的依赖程度越小&#xff0c;则其耦合程度也就越小。 很显然&#xff0c;为了使软件具有较好的可维护性和可修改性&#xf…...

OCT介绍和分类

前言&#xff1a;研究方向和OCT有关&#xff0c;为了方便以后回顾&#xff0c;所以整理了OCT相关的一些内容。 OCT介绍和分类 OCT介绍分类时域OCT频域OCT扫频OCT谱域OCT OCT介绍 名称&#xff1a;OCT、光学相干层析成像术、Optical Coherence Tomography。 概念&#xff1a;O…...

07-2_Qt 5.9 C++开发指南_二进制文件读写(stm和dat格式)

文章目录 1. 实例功能概述2. Qt预定义编码文件的读写2.1 保存为stm文件2.2 stm文件格式2.3 读取stm文件 3. 标准编码文件的读写3.1 保存为dat文件3.2 dat文件格式3.3 读取dat文件 4. 框架及源码4.1 可视化UI设计4.2 mainwindow.cpp 1. 实例功能概述 除了文本文件之外&#xff…...

SpringBoot复习:(41)配置文件中配置的server开头的属性是怎么配置到Servlet容器中起作用的?

ServletWebServerFactoryAutoConfiguration类&#xff1a; 可以看到其中使用了EnableConfigurationProperties导入了ServerProperties 而ServerProperties通过使用ConfigurationProperties注解导入了配置文件中已server开头的那些配置项。 可以看到ServletWebServerFactory定…...

深入解读网络协议:原理与重要概念

目录 TCP/IP协议 IP地址 子网掩码 DNS 网关 网络端口 TCP/IP协议 TCP/IP是互联网通信的基础协议。它由两个部分组成&#xff1a;TCP负责数据的可靠传输&#xff0c;确保数据按序到达目标&#xff1b;IP负责寻址和路由&#xff0c;确保数据在网络中正确传递。TCP/IP协议簇…...

O型圈不同类型的应用指南

O型圈因其优异的密封性能而广泛应用于各个行业和应用。它们简单、经济高效且密封可靠&#xff0c;下面我们了解一下适合每种应用的特定类型的O型圈。 1、汽车行业 在汽车行业中&#xff0c;O型圈在密封发动机部件和防止机油或冷却剂泄漏方面发挥着至关重要的作用。常见应用包…...

Mysql 搭建MHA高可用架构,实现自动failover,完成主从切换

目录 自动failover MHA&#xff1a; MHA 服务 项目&#xff1a;搭建Mysql主从复制、MHA高可用架构 实验项目IP地址配置&#xff1a; MHA下载地址 项目步骤&#xff1a; 一、修改主机名 二、编写一键安装mha node脚本和一键安装mha mangaer脚本&#xff0c;并执行安装…...

Python:列表、元组、集合、字典,数据类型之间的 5 个差异

Python&#xff1a;列表、元组、集合、字典&#xff0c;数据类型之间的 5 个差异 1. 相同点2. 不同点2.1 排序2.2 索引2.3 可变性2.5 允许的类型2.4 允许重复 源码 这篇博客将介绍列表、元组、集合、字典&#xff08;lists, tuples, sets, and dictionaries&#xff09;数据类型…...

redis学习笔记(四)

文章目录 list&#xff08;数组&#xff09;&#xff08;1&#xff09;添加子成员&#xff08;2&#xff09;基于索引获取列表成员&#xff08;3&#xff09;获取列表的切片&#xff08;4&#xff09;获取列表的长度&#xff08;5&#xff09;按索引设置值&#xff08;6&#x…...

-L和-rpath-link和-rpath

知识点 现代连接器在处理动态库时将链接时路径&#xff08;Link-time path&#xff09;和运行时路径&#xff08;Run-time path&#xff09;分开,用户可以通过-L指定连接时库的路径&#xff0c;通过-R&#xff08;或-rpath&#xff09;指定程序运行时库的路径&#xff0c;大大提…...

chatGPT小白快速入门培训课程-001

一、前言 本文是《chatGPT小白快速入门培训课程》的第001篇文章&#xff0c;全部内容采用chatGPT和chatGPT开源平替软件生成。完整内容大纲详见&#xff1a;《chatGPT小白快速入门课程大纲》。 本系列文章&#xff0c;参与&#xff1a; AIGC征文活动 #AIGC技术创作内容征文# …...

【Linux操作系统】深入理解Linux系统编程中的传入参数、传出参数和传入传出参数

在Linux系统编程中&#xff0c;函数的参数扮演着至关重要的角色。参数的传递方式可以分为传入参数、传出参数和传入传出参数。本文将详细解释这三种参数的概念、特点以及如何使用它们来实现灵活和高效的函数调用和数据传递。 文章目录 1. 解释和举例1.1 传入参数&#xff08;i…...

(二)结构型模式:3、过滤器模式(Filter、Criteria Pattern)(C++示例)设计模式

目录 1、过滤器模式&#xff08;Filter、Criteria Pattern&#xff09;含义 2、过滤器模式应用场景 3、过滤器模式主要几个关键角色 4、C实现过滤器模式的示例 1、过滤器模式&#xff08;Filter、Criteria Pattern&#xff09;含义 &#xff08;1&#xff09;过滤器模式是…...

欧拉OS 使用 CentOS 7 yum repo

一、下载CentOS的repo的yum文件 任何基于CentOS的yum的repo 的url是这样的&#xff1a; 但欧拉OS输出这个变量为&#xff1a;openEuler 20.03 (LTS-SP3) 那明显欧拉想要使用这个yum的url找不到这个版本&#xff0c; 所以直接讲这个变量替换为 7, Centos 7的7 然后执行&…...

C进阶(1/7)——数据在内存中的存储

目录 前言&#xff1a; 一.数据类型介绍 类型基本归类&#xff1a; 整型家族&#xff1a; 浮点数家族&#xff1a; 构造类型&#xff1a; ​指针类型&#xff1a; 空类型&#xff1a; 二.整型在内存中的存储 1.原码&#xff0c;反码&#xff0c;补码 2.大小端介绍 3.练…...

如何初始化Git仓库

如何将目录初始化为Git仓库 一级目录二级目录三级目录 一、准备1、安装 gh2、登录 二、初始化 Git 仓库 一级目录 二级目录 三级目录 一、准备 ​ 在这里&#xff0c;我们需要借助一个非常好用的工具&#xff0c;大家也可以参照官方文档进行阅读&#xff0c;下面介绍常用的…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...

Caliper 配置文件解析:fisco-bcos.json

config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...

小木的算法日记-多叉树的递归/层序遍历

&#x1f332; 从二叉树到森林&#xff1a;一文彻底搞懂多叉树遍历的艺术 &#x1f680; 引言 你好&#xff0c;未来的算法大神&#xff01; 在数据结构的世界里&#xff0c;“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的&#xff0c;它…...

Java后端检查空条件查询

通过抛出运行异常&#xff1a;throw new RuntimeException("请输入查询条件&#xff01;");BranchWarehouseServiceImpl.java // 查询试剂交易&#xff08;入库/出库&#xff09;记录Overridepublic List<BranchWarehouseTransactions> queryForReagent(Branch…...