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

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

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

相关推荐
z202305081 分钟前
linux 之0号进程、1号进程、2号进程
linux·运维·服务器
HinsCoder18 分钟前
【渗透测试】——Upload靶场实战(1-5关)
笔记·学习·安全·web安全·渗透测试·测试·upload靶场
听风若依21 分钟前
排序学习笔记
笔记·学习
秋已杰爱22 分钟前
HTTP中的Cookie与Session
服务器·网络协议·http
Filotimo_25 分钟前
【自然语言处理】实验三:新冠病毒的FAQ问答系统
人工智能·经验分享·笔记·python·学习·自然语言处理·pycharm
IM_DALLA32 分钟前
【Verilog学习日常】—牛客网刷题—Verilog快速入门—VL21
学习·fpga开发
狐心kitsune34 分钟前
erlang学习:Linux常用命令1
linux·学习·erlang
小游鱼KF1 小时前
Spring学习前置知识
java·学习·spring
code bean1 小时前
【C#基础】函数传参大总结
服务器·开发语言·c#
shelby_loo1 小时前
通过 Docker 部署 WordPress 服务器
服务器·docker·容器