管道分类: 根据进程的相互关系,可以分为:匿名管道与命名管道
(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: //errorperror( "fork" );break;case 0: //child processclose(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; }