1.基本原理
管道是最基本的IPC(InterProcess Communication)进程间通信
我们知道进程有4G的虚拟内存,其中0到3G是独立的进程空间,每个进程不相互通,而3G-4G是公用的内核空间。要实现在进程间传递数据,管道就是利用这公用的内核空间来完成,即利用内核的一块缓冲区
2.基本使用
#incldue<unistd.h>
int pipe(int fd[2]);
fd返回两个文件描述符fd[0]为读,fd[1]为写。fd[1]的输出是fd[0]的输入。
通过文件描述符去索引管道,单向通信。
先pipe,后fork。
测试代码如下:
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
int main(){
int fd[2];
pid_t pid;
char str[1024]="hello itcast";
char buf[1024];
//fd[0] 读端
//fd[1] 写端
if(pipe(fd)<0){
perror("pipe");
exit(1);
}
pid=fork();
//父写子读
if(pid>0){
//关闭父读
close(fd[0]);
sleep(2);
write(fd[1],str,strlen(str));
wait(NULL);
}else if(pid==0){
int len;
//子进程关闭写端
close(fd[1]);
len=read(fd[0],buf,sizeof(buf));
//读时共享,写时复制 可以直接读str
// sprintf(str,"child %s",buf);
write(STDOUT_FILENO,buf,len);
}
else{
perror("fork");
exit(1);
}
return 0;
}
2.两个局限性
(1)管道是半双工的(即数据只能在一个方向上流动)
(2)只能在具有公共祖先的两个进程之间使用(具有血缘关系)
(1)方向性
根据其特点,管道是用数据结构--环形队列完成的,写端入队,读端出队。
若队列满了,就会阻塞,等到有空间继续运行。
(2)血缘性
首先要确定父写子读,还是子写父读
为什么不能双向?
因为父子进程中PCB的文件描述符相同,指向同一个file结构体,若都写或者都读,造成歧义,会造成通信的混乱。
注意事项:
13)信号SIGPIPE
fpathconf(int fd ,int name)测试管道缓冲区大小,"
"name"参数_PC_PIPE_BUF
测试大小为64K