管道又称匿名管道,是半双工的的进程间通信,由于没有名字所以只能在父子进程间使用,其他进程是无法获得其管道描述符的。
特点
- 管道是半双工模式,同一时间一端只能接收或发送数据。
- 管道是创建在内存中的,意味着进程结束后管道就不存在了。
- 如果管道中没有数据,则读取管道数据的进程会发生读阻塞。
- 如果管道被写满了,则会发生写阻塞。
使用场景
仅适用于父子进程间的通信,且一端只读,一端只写。因为是匿名管道所,其他进程是无法获得其管道描述符的。
创建管道
创建管道需要准备int fd[2]
的数组,fd[0]
是读管道,fd[1]
是写管道。调用pipe()
函数创建管道。
示例代码
#include <iostream>
#include <unistd.h>
using namespace std;
#define PIPE_READ 0
#define PIPE_WRITE 1
int main()
{
pid_t fpid = 0;
int ret = 0;
int fd[2];
// 创建管道,成功后fd[0]是read pipe,fd[1]是write pipe
if (0 != pipe(fd)) {
cout << "pipe error!" << endl;
exit(1);
}
// 创建子进程
fpid = fork();
if (fpid > 0) {
// 父进程,此时fpid是子进程的pid
// 管道是半双工的,这里父进程关闭read pipe,然后给子进程发送数据
cout << "I am father, my pid is " << getpid() << endl;
close(fd[PIPE_READ]);
// 为了体现读阻塞,主进程5秒后再写入数据,可以观察到5秒后子进程才输出 “Hi!”
sleep(5);
write(fd[PIPE_WRITE], "Hi!\n", 4);
} else if (0 == fpid) {
// 子进程
// 管道是半双工的,这里子进程关闭write pipe,然后读取父进程发来的数据
cout << "I am child, my pid is " << getpid() << endl;
close(fd[PIPE_WRITE]);
char buf[4] = {};
read(fd[PIPE_READ], buf, sizeof(buf));
cout << "Child received data: " << string(buf) << endl;
} else {
cout << "fork failed!" << endl;
}
return 0;
}