无名管道的局限性:
1)虽然某些系统提供全双工管道,但是为了可移植性,不能预先假定系统支持全双工管道
2)管道只能在具有公共祖先的两个进程间使用。(一般都是父子进程)
无名管道是调用pipe函数创建的:
#include <unistd.h>
int pipe(int fd[2]);
返回值:若成功,返回0;若出错,返回-1
由参数fd返回两个文件描述符:fd[0]为读而打开,fd[1]为写而打开。fd[1]的输出是fd[0]的输入。
进程通常会调用pipe,接着调用fork,从而创建从父进程到子进程的IPC通道。
# 管道通讯是单向的(只创建一个管道),有固定的读端和写端。
# 数据被进程从管道读出后,在管道中该数据就不存在了。
# 当进程去读取空管道的时候,进程会阻塞。
# 当进程往满管道写入数据时,进程会阻塞。(管道有容量大小)
fork之后做什么取决于想要的数据流方向:
从父进程到子进程的管道,父进程关闭管道的读端(fd[0]),子进程关闭写段(fd[1]);
从子进程到父进程的管道,父进程关闭管道的写端(fd[1]),子进程关闭读端(fd[0])。
//单向通信:父进程到子进程的管道
1 #include <stdio.h> 2 #include <unistd.h> 3 4 int main() 5 { 6 int fd[2]; 7 pid_t pid; 8 char content[1024] = {}; 9 10 if(pipe(fd) < 0) 11 perror("pipe error"); 12 if((pid = fork()) < 0) 13 { 14 perror("fork error"); 15 } 16 else if(pid > 0) /*parent*/ 17 { 18 close(fd[0]); //关闭父进程的读端 19 write(fd[1], "this is apple", 13); 20 } 21 else /*child*/ 22 { 23 close(fd[1]); //关闭子进程的写端 24 read(fd[0], content, 1024); 25 printf("%s\n", content); 26 } 27 28 return 0; 29 }
//双向通信:方法就是创建两个管道
1 #include <stdio.h> 2 #include <unistd.h> 3 4 int main() 5 { 6 int fd1[2], fd2[2]; 7 pid_t pid; 8 char content1[1024] = {}; 9 char content2[1024] = {}; 10 11 if(pipe(fd1) < 0) 12 perror("pipe error"); 13 14 if(pipe(fd2) < 0) 15 perror("pipe error"); 16 17 if((pid = fork()) < 0) 18 { 19 perror("fork error"); 20 } 21 else if(pid > 0) /*parent*/ 22 { 23 close(fd1[0]); //关闭 管道一 父进程的读端 24 write(fd1[1], "this is pipe1 data!", 19); 25 26 close(fd2[1]); //关闭 管道二 父进程的写端 27 read(fd2[0], content2, 1024); 28 29 printf("%s\n", content2); 30 } 31 else /*child*/ 32 { 33 close(fd1[1]); //关闭 管道一 子进程的写端 34 read(fd1[0], content1, 1024); 35 36 printf("%s\n", content1); 37 38 close(fd2[0]); //关闭 管道二 子进程的读端 39 write(fd2[1], "this is pipe2 data!", 19); 40 } 41 42 return 0; 43 }