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

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

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

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

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

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

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

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

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的过程中,当一个进程对管道进行写操作时:

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

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

相关推荐
Lovyk32 分钟前
Linux 系统启动原理
linux·服务器·windows
Jewel Q1 小时前
TCP为什么采用三次握手而不是二次握手
服务器·网络·tcp/ip
藏在歌词里1 小时前
Linux-Shell脚本基础用法
linux·运维·服务器
NfN-sh1 小时前
计数组合学7.12( RSK算法的一些推论)
笔记·学习·算法
Sadsvit1 小时前
Linux 服务器性能监控、分析与优化全指南
java·linux·服务器
农夫山泉(代码版)1 小时前
Linux驱动学习(七)平台总线框架
linux·服务器·学习
通信小小昕1 小时前
Petalinux快捷下载
linux
驱动起爆大师x_x1 小时前
STM32_Hal库学习SPI
stm32·嵌入式硬件·学习
小眼睛FPGA1 小时前
【盘古100Pro+开发板实验例程】FPGA学习 | 基于 UDP 的以太网传输实验例程
科技·单片机·学习·ai·fpga开发·fpga
Neng_Miao1 小时前
用户与组管理命令
linux·运维