第六章 进程通信之管道
管道分类: 根据进程的相互关系,可以分为:匿名管道与命名管道
(1) 匿名管道 pipe
#include <unistd.h> int pipe(int pipes[2]);
管道是父进程和子进程间 单向的通讯机制。通过上述函数创建管道 会在内存开辟一块缓冲区,pipes[0] 读端,1写端。默认的是阻塞模式。 下面是一个简单的例子:
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> void read_from_pipe(int pipe) { char ch; while(read(pipe, &ch, sizeof(char)) > 0 ) //block read { printf("pipe read :%c \n",ch); } } void write_to_pipe(int pipe) { char ch = 0; printf("please write string to write in pipe !\n"); while( (ch=getchar()) > 0 ) { if(write(pipe, &ch, sizeof(char) ) == -1) { break; } printf("pipe write :%c \n",ch); } } int main(void) { int pipes[ 2 ]; pid_t pid; if(pipe( pipes ) == -1) { perror( "pipes" ); return -1; } pid = fork( ); switch( pid ) { case -1: //error perror( "fork" ); break; case 0: //child process close(pipes[1]); read_from_pipe( pipes[0] ); close(pipes[0]); break; default: close(pipes[0]); write_to_pipe( pipes[1] ); close(pipes[1]); break; } return 0; }
(2) 命名管道 FIFO
#include <sys/stat.h> #include <sys/types.h> int mkfifo(const char * filename,mode_t mode);
命名管道又称FIFO (FIRST IN FIRST OUT). 它是文件系统中的特殊文件(注意是文件哦,一般我们可以把它放在/tmp/xxxx里). 只不过该文家具有管道的特性。数据读出时,fifo管道中的数据会被清除。
管道的操作如同文件操作。不同的是 使用 mkfifo 创建 ,unlink删除。
(3)popen 的使用
popen()是一个系统函数,它完成fork()产生一个子进程,然后从子进程调用(即使用shell)来执行command的指令。父进程通过它得到子进程返回的文件描述符 。
简单解析popen 的实现原理,采用pipe通信机制 ,重定向pipe 到标准输入输出流,返回子进程执行结果。其实popen 的返回值相当于pipe[0],只是把它标准输入流重定向到pipe[1];
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> int main() { FILE *fp; char *cmd = "ls -l"; char line [ 1024 ]; fp = popen( cmd, "r" ); if( !fp ) { perror( "popen error" ); exit( 1 ); } while( fgets( line, sizeof( line ), fp) ) { printf( "%s", line ); } return 0; }