运行环境
- win11 linux子系统Ubuntu2204
- g++ 11.3.0
Linux DESKTOP-XXXXX 5.15.79.1-microsoft-standard-WSL2 #1 SMP Wed Nov 23 01:01:46 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
管道的概念
管道是一种最基本的IPC机制,作用于有血缘关系的进程之间,完成数据传递。调用pipe系统函数即可创建一个管道。有如下特质:
-
其本质是一个伪文件(实为内核缓冲区)
-
由两个文件描述符引用,一个表示读端,一个表示写端。
-
规定数据从管道的写端流入管道,从读端流出。
管道的原理: 管道实为内核使用环形队列机制,借助内核缓冲区(4k)实现。
管道的局限性:
① 数据自己读不能自己写。
② 数据一旦被读走,便不在管道中存在,不可反复读取。
③ 由于管道采用半双工通信方式。因此,数据只能在一个方向上流动。
④ 只能在有公共祖先的进程间使用管道。
常见的通信方式有,单工通信、半双工通信、全双工通信。
pipe函数
创建管道:
- int pipe(int pipefd[2]); 成功:0;失败:-1,设置errno
函数调用成功返回r/w两个文件描述符。无需open,但需手动close。规定:fd[0] → r; fd[1] → w,就像0对应标准输入,1对应标准输出一样。向管道文件读写数据其实是在读写内核缓冲区。
父子进程使用pipe通讯
简单示例:
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
#include <strings.h>
int main(int argc, char const* argv[])
{
int fd[2];
if (pipe(fd) == -1)
{
perror("管道创建失败");
}
pid_t pid = fork();
if (pid > 0)
{
// 父进程,读端:fd[0]
char buf[256];
bzero(buf, 256);
read(fd[0], buf, 256);
printf("child say %s\n", buf);
wait(NULL);
}
else if (pid == 0)
{
// 子进程,写端:fd[1]
char s[256] = { "hello father." };
write(fd[1], s, strlen(s));
exit(0);
}
else {
printf("进程创建失败\n");
}
close(fd[0]);
close(fd[1]);
return 0;
}