标签:
管道是一种只允许用在有亲属关系的进程间通信的方式,由函数pipe创建一个管道,read,write进行读写操作。
#include <unistd.h> int pipe(int pipefd[2]);
参数pipefd[2]数组返回打开的读写描述符,pipefd[0]为读,pipefd[1]为写。
第一个问题:文件描述符怎么会出现一个只能读,一个只能写呢?猜想是对一个文件打开了2次,一个以只读打开,一个以只写打开。使用fcntl来验证下:
#include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd, ... /* arg */ );
F_GETFL (void) Get the file access mode and the file status flags; arg is ignored.
cmd为F_GETFL时,最后一个参数arg被忽略。测试代码:
1 #include <sys/types.h> 2 #include <sys/stat.h> 3 #include <stdio.h> 4 #include <fcntl.h> 5 #include <signal.h> 6 #include <unistd.h> 7 #include <stdlib.h> 8 9 int main(void) 10 { 11 int flags; 12 int fd[2]; 13 14 if (pipe(fd) < 0) 15 { 16 perror("pipe error"); 17 } 18 19 flags = fcntl(fd[0], F_GETFL,0); 20 if ( flags < 0 ) 21 { 22 perror("fcntl"); 23 close(fd[0]); 24 close(fd[1]); 25 } 26 switch (flags & O_ACCMODE) 27 { 28 case O_RDONLY: 29 printf("read only\n"); 30 break; 31 32 case O_WRONLY: 33 printf("write only\n"); 34 break; 35 36 case O_RDWR: 37 printf("read write\n"); 38 break; 39 40 default: 41 printf("unknown access mode\n"); 42 } 43 44 flags = fcntl(fd[1], F_GETFL,0); 45 if ( flags < 0 ) 46 { 47 perror("fcntl"); 48 close(fd[0]); 49 close(fd[1]); 50 } 51 switch (flags & O_ACCMODE) 52 { 53 case O_RDONLY: 54 printf("read only\n"); 55 break; 56 57 case O_WRONLY: 58 printf("write only\n"); 59 break; 60 61 case O_RDWR: 62 printf("read write\n"); 63 break; 64 65 default: 66 printf("unknown access mode\n"); 67 } 68 close(fd[0]); 69 close(fd[1]); 70 exit(0); 71 }
运行结果:
read only
write only
与猜想相符。
数据的流向:
从图中可以看出,进程可以以pipefd[1]写完,然后以pipefd[0]读,自己写自己读,这条数据流是通的。 验证:
1 #include <sys/types.h> 2 #include <sys/stat.h> 3 #include <stdio.h> 4 #include <fcntl.h> 5 #include <signal.h> 6 #include <unistd.h> 7 #include <stdlib.h> 8 9 #define MAXLINE 4096 10 int main(void) 11 { 12 int flags; 13 int fd[2], n; 14 char buf[MAXLINE]; 15 if (pipe(fd) < 0) 16 { 17 perror("pipe error"); 18 } 19 20 n = write(fd[1], "hello world\n", MAXLINE); 21 if ( n < 0 ) 22 { 23 perror("write"); 24 goto end; 25 } 26 n = read(fd[0],buf, n); 27 if ( n < 0 ) 28 { 29 perror("read"); 30 goto end; 31 } 32 printf("read:%s\n",buf); 33 34 end: 35 close(fd[0]); 36 close(fd[1]); 37 exit(0); 38 }
输出:
read:hello world
既然是进程间通信,那么管道在同一个进程中读写基本是没什么意义的,管道常用的方式是,先创建一个管道,然后fork,父子进程就共享了这个管道了。数据流向如图:
这样,管道的写端有2个进程操作,读端有2个进程操作。但是这样一来就出现了一个问题,假设父进程读,那么这个数据是它自己写进去的呢?还是子进程写进去的?无法区分。通常一个进程关闭它的读,另一个进程关闭它的写,这样,数据流向就只有一个方向了,数据来自谁就显而易见了。如图:
测试代码:
1 #include <sys/types.h> 2 #include <sys/stat.h> 3 #include <stdio.h> 4 #include <fcntl.h> 5 #include <signal.h> 6 #include <unistd.h> 7 #include <stdlib.h> 8 #include <string.h> 9 10 #define MAXLINE 4096 11 12 int main(void) 13 { 14 int n; 15 int fd[2]; 16 pid_t pid; 17 char line[MAXLINE]; 18 19 if (pipe(fd) < 0) 20 perror("pipe error"); 21 if ((pid = fork()) < 0) 22 { 23 perror("fork error"); 24 } 25 else if (pid > 0) /* parent */ 26 { 27 close(fd[0]); 28 write(fd[1], "hello world\n", 12); 29 } 30 else /* child */ 31 { 32 close(fd[1]); 33 n = read(fd[0], line, MAXLINE); 34 write(STDOUT_FILENO, line, n); 35 } 36 exit(0); 37 }
结果:
hello world
标签:
原文地址:http://www.cnblogs.com/thammer/p/5093330.html