【Linux】学习记录_10_管道

10 管道

数据可以从一个进程流向另一个进程

10.1 匿名管道PIPE

匿名管道有以下的特征:

  • 没有名字,因此不能使用open()函数打开,但可以使用close()函数关闭。

  • 只提供单向通信(半双工),也就是说,两个进程都能访问这个文件,假设进程1往文件内写东西, 那么进程2就只能读取文件的内容。

  • 只能用于具有血缘关系的进程间通信,通常用于父子进程建通信 。

  • 管道是基于字节流来通信的。

  • 依赖于文件系统,它的生命周期随进程的结束而结束。

  • 写入操作不具有原子性,因此只能用于一对一的简单通信情形。

  • 管道也可以看成是一种特殊的文件,对于它的读写也可以使用普通的read()和write()等函数。 但是它又不是普通的文件,并不属于其他任何文件系统,并且只存在于内核的内存空间中, 因此不能使用lseek()来定位。

10.2 命名管道FIFO

命名管道有以下的特征:

  • 有名字,存储于普通文件系统之中。

  • 任何具有相应权限的进程都可以使用 open()来获取命名管道的文件描述符。

  • 跟普通文件一样:使用统一的 read()/write()来读写。

  • 跟普通文件不同:不能使用 lseek()来定位,原因是数据存储于内存中。

  • 具有写入原子性,支持多写者同时进行写操作而数据不会互相践踏。

  • 遵循先进先出(First In First Out)原则,最先被写入 FIFO的数据,最先被读出来。

10.3 pipe()函数

c 复制代码
int pipe(int pipefd[2]);

数组pipefd是用于返回两个引用管道末端的文件描述符, pipefd0 指管道的读取端,pipefd1指向管道的写端 , 向管道的写入端写入数据将会由内核缓冲,即写入内存中,直到从管道的读取端读取数据为止, 而且数据遵循先进先出原则。pipe()函数还会返回一个int类型的变量, 如果为0则表示创建匿名管道成功,如果为-1则表示创建失败,并且设置errno。

匿名管道创建成功以后,创建该匿名管道的进程(父进程)同时掌握着管道的读取端和写入端, 但是想要父子进程间有数据交互,则需要以下操作:

  • 父进程调用pipe()函数创建匿名管道,得到两个文件描述符pipefd0、pipefd1, 分别指向管道的读取端和写入端。

  • 父进程调用fork()函数启动(创建)一个子进程, 那么子进程将从父进程中继承这两个文件描述符pipefd0、pipefd1, 它们指向同一匿名管道的读取端与写入端。

  • 由于匿名管道是利用环形队列实现的,数据将从写入端流入管道,从读取端流出,这样子就实现了进程间通信, 但是这个匿名管道此时有两个读取端与两个写入端。

  • 如果想要从父进程将数据传递给子进程,则父进程需要关闭读取端,子进程关闭写入端

  • 如果想要从子进程将数据传递给父进程,则父进程需要关闭写入端,子进程关闭读取端

  • 当不需要管道的时候,就在进程中将未关闭的一端关闭即可

10.4 fifo()函数

c 复制代码
int mkfifo(const char * pathname,mode_t mode);

mkfifo()会根据参数pathname建立特殊的FIFO文件,而参数mode为该文件的模式与权限。

mkfifo()创建的FIFO文件其他进程都可以进行读写操作,可以使用读写一般文件的方式操作它, 如open,read,write,close等。

mode模式及权限参数说明:

  • O_RDONLY:读管道。

  • O_WRONLY:写管道。

  • O_RDWR:读写管道。

  • O_NONBLOCK:非阻塞。

  • O_CREAT:如果该文件不存在,那么就创建一个新的文件,用第三个参数为其设置权限

  • O_EXCL:如果使用O_CREAT时文件存在,那么可返回错误消息。可测试文件是否存在。

函数返回值说明如下:

  • 0:成功

  • EACCESS:参数 filename 所指定的目录路径无可执行的权限。

  • EEXIST:参数 filename 所指定的文件已存在。

  • ENAMETOOLONG:参数 filename 的路径名称太长。

  • ENOENT:参数 filename 包含的目录不存在。

  • ENOSPC:文件系统的剩余空间不足。

  • ENOTDIR:参数 filename 路径中的目录存在但却非真正的目录。

  • EROFS:参数 filename 指定的文件存在于只读文件系统内。

使用FIFO的过程中,当一个进程对管道进行读操作时:

  • 若该管道是阻塞类型,且当前FIFO内没有数据,则对读进程将一直阻塞到有数据写入。

  • 若该管道是非阻塞类型,不论FIFO内是否有数据,读进程都会立即执行读操作。 即如果FIFO内没有数据,读函数将立刻返回 0。

使用FIFO的过程中,当一个进程对管道进行写操作时:

  • 若该管道是阻塞类型,则写操作将一直阻塞到数据可以被写入。

  • 若该管道是非阻塞类型而不能写入全部数据,则写操作进行部分写入或者调用失败

相关推荐
程序员清风5 小时前
数据处理脚本工程化:日志、配置、命令行与测试
服务器·开发语言·数据库
学长毕设5 小时前
基于SpringBoot的青少年编程学习平台系统-附源码
spring boot·学习·青少年编程
readhere6 小时前
从ZYNQ7000开发板,学会启动嵌入式Linux系统——入门学习:EBAZ4205篇目录
linux·启动·嵌入式linux·zynq7000·ebaz4205
打工仔折腾 AI7 小时前
在 Ubuntu ARM64 部署 Q1 V3.0 MuJoCo 模型:加载、单步推理与执行器响应解析
linux·运维·人工智能·python·深度学习·ubuntu·性能优化
yyuuuzz7 小时前
跨境站点日志时区混乱的排查记录
运维·服务器·网络·云计算·aws·1024程序员节
‎ദ്ദിᵔ.˛.ᵔ₎7 小时前
关于Linux 线程局部存储的认识
linux·运维
数字新视界9 小时前
一体化机柜在数据中心运维中的创新应用与优势分析
大数据·服务器·数据库·动环监控系统·动力与环境监控系统
运维行者_9 小时前
网络监控工具怎么选?从设备监控到智能运维的能力清单
运维·服务器·开发语言·网络·人工智能·支持向量机·php
小小de风呀9 小时前
de风——【从零开始学习Linux】(九):进程基础 —— 从冯诺依曼体系到 fork 创建进程
linux·学习
2401_868534789 小时前
陈冲2026年上海纽约大学全英文毕业演讲
服务器·网络