管道(Pipe)是操作系统提供的一种进程间通信(IPC,Inter-Process Communication)机制,它允许一个进程的输出直接作为另一个进程的输入。管道主要分为以下两种类型:
无名管道(Unnamed Pipe):
int fd[2]
,其中fd[0]
用于读取,fd[1]
用于写入。命名管道(Named Pipe或FIFO,First-In-First-Out):
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main() {
int pipefd[2];
pid_t cpid;
char buf;
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { // 子进程
close(pipefd[1]); // 关闭管道的写端
while (read(pipefd[0], &buf, 1) > 0) { // 从管道的读端读数据
write(STDOUT_FILENO, &buf, 1); // 将读到的数据输出到标准输出
}
write(STDOUT_FILENO, "\n", 1);
close(pipefd[0]); // 关闭管道的读端
_exit(EXIT_SUCCESS);
} else { // 父进程
close(pipefd[0]); // 关闭管道的读端
write(pipefd[1], "Hello, world!", 13); // 向管道的写端写数据
close(pipefd[1]); // 关闭管道的写端
wait(NULL); // 等待子进程结束
exit(EXIT_SUCCESS);
}
}
在上面的例子中,首先使用pipe()
函数创建了一个管道,并获取了管道的两个文件描述符。然后,使用fork()
函数创建了一个子进程。在子进程中,关闭了管道的写端,然后从管道的读端读取数据,并将读到的数据输出到标准输出。在父进程中,关闭了管道的读端,然后向管道的写端写入数据,并等待子进程结束。最后,在父进程中关闭了管道的写端,并结束了整个程序。
需要注意的是,管道是一种半双工的通信方式,数据只能单向流动。在上述例子中,创建了一个管道,并使用fork()
函数创建了一个子进程。然后,在父进程中向管道的写端写入数据,在子进程中从管道的读端读取数据。由于管道是单向的,所以需要使用两个文件描述符来实现父子进程之间的双向通信。
管道的主要特点和注意事项包括:
- 管道中的数据是以字节流的形式传输的,不保留消息边界。
- 管道的读写操作遵循先进先出(FIFO)的原则。
- 管道的读端和写端都是独立的文件描述符,可以被不同的进程拥有。
- 如果没有进程在读取管道中的数据,那么写入管道的操作可能会阻塞,直到有进程开始读取。
- 当所有引用管道的进程都关闭了它们的文件描述符时,管道将被删除。