导航
当前章节:管道
原文链接:管道
上一章节:进程
下一章节:线程
目录:Linux程序设计
管道
介绍
管道是Linux中进程间通信的一种形式。它们允许一个过程的输出变成另一个过程中的输入。
在此之前需要先理解一个概念。linux将进程的通信管道,文件是一个实体,使用文件描述符指向对应文件,文件描述符是一个整型数据,从0开始递增。
如当创建一个进程时默认存在stdin标准输入0(dev/stdin),stdout标准输出1,stderror标准错误2。创建子进程会继承文件描述符。
创建管道时会返回两个文件描述符,一个写一个读,通过write和read可以实现进程通信。
管道有几个关键点:
- 管道是使用pipe()系统调用创建的。这返回两个文件描述符,一个用于读取(fd[0]),另一个用于写入(fd[1])。
- pipe()返回的文件描述符在默认情况下是不可继承的。我们需要使用dup2()将它们传递给子进程。
- 如果没有要读取的数据(管道为空),则从管道读取将被阻止。对完整管道的写入也将被阻止。
- 管道的容量有限,通常在4kB到64kB之间。如果达到此容量,将阻止进一步的写入操作。
- 关闭管道的读取端会导致写入端接收EOF(文件结束)。对管道的进一步写入将导致SIGPIPE信号。当所有数据都已被读取时,关闭写入端会导致读取端接收EOF。
- 管道允许相关进程以简单的方式进行通信。进程可以是父进程和子进程,也可以是共享管道的不相关进程。
父子进程通信
1 | int fd[2]; |
不相关两个进程通信
1 | int fd[2]; |
dup函数实现重定向
#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);
dup会将返回一个新文件描述符,这个描述符是当前可用的最小描述符,并且为传入的旧文件描述符的值,即该文件描述符指向的文件是原文件
dup2实现对输入输出等文件描述符重定向,例如父子进程将标准输入输出赋值为管道的输入输出,就能实现通过标准输入输出通信。
要注意的是,stdin 是一个指向标准输入的流对象,在底层实现中使用了文件描述符 STDIN_FILENO 来表示标准输入。
例如 dup2(fd[0], STDIN_FILENO) 就是将管道的读取端复制到了 stdin 所代表的标准输入上,使得之后对 stdin 的读取实际上是从管道中读取数据。
1 | int fd[2]; |
dup2()执行以下操作:
如果newfd已经存在,则首先关闭它。
oldfd与newfd重复。
newfd与oldfd共享相同的文件位置指针和文件状态标志。
这两个文件描述符可以互换使用。
对任何一个文件描述符的读取和写入都将对同一个文件进行操作。
dup2()用于将一个文件描述符复制到另一个,同时共享底层资源。
它通常用于重定向进程中的标准I/O流。
dup2()到一个关闭的文件描述符将打开它,然后复制到它。
dup2()导致原始fd关闭,而新fd引用相同的文件。
重复的fds共享文件位置指针和文件状态标志。