管道常用于不同命令的组合使用,比如ps -aux|grep ..用于查找指定条件的进程,ls|less用于实现文件列表的分页显示等。总之是将前一个命令的输出作为后一个命令的输入,完成一个命令无法完成的功能。
分别使用pipe()和popen()两种方式实现ls|less(ls|more)的功能。
gao.lu.c
gao.lu.c~
ls.o
pipedup
test1
test2
test3
test4
【1】使用pipe()实现
pipe()函数可以生成2个文件描述符,分别指向管道的read和write端,创建子进程,然后在父子进程内部分别执行ls和less命令,前者将标准输出重定向到管道,后者将标准输入重定向到管道。
#include
#include
int main(int argc,char* argv[])
{
int f_des[2]; //f_des[0]:for read, f_des[1]:for write.
int pid;
if(argc != 3)
{
printf("Usage: %s comand1,comand2.\n",argv[0]);
return 1;
}
if(pipe(f_des)==-1)
{
perror("Fail to creat pipe.\n");
return 1;
}
if((pid=fork())==-1)
{
perror("Fail to creat child process.\n");
return 1;
}
if(pid==0)
{
dup2(f_des[0],STDIN_FILENO);
close(f_des[0]);
close(f_des[1]);
if(execlp(argv[1],argv[1],NULL)==-1)
{
printf("Child process can't exec command %s.\n",argv[1]);
return 1;
}
_exit(0);
}
else
{
dup2(f_des[1],STDOUT_FILENO);
close(f_des[0]);
close(f_des[1]);
if(execlp(argv[2],argv[2],NULL)==-1)
{
printf("Parent process can't exec command %s.\n",argv[2]);
return 1;
}
wait(NULL);
_exit(0);
}
return 0;
}
执行结果:
【2】使用popen()实现
有warnning(fs貌似应该做个强制类型转换再dup么)。相当于在上面pipe()的实现中,让父进程调用通过execlp执行ls命令,将标准输出重定向到管道,而子进程从管道中去数据执行less打印到标准输出。
#include
#include
int main (int argc,char* argv[])
{
if(argc != 3)
{
printf("Usage: %s comand1, comand2.\n",argv[0]);
return 1;
}
FILE* fs = popen(argv[2],"w");
if(NULL == fs)
{
perror("Call popen function failed.\n");
return 1;
}
dup2(fs,STDOUT_FILENO);
if(execlp(argv[1],NULL)==-1)
{
printf("Exec command %s failed.\n",argv[1]);
return 1;
}
pclose(fs);
exit(0);
}
执行结果:
http://keren.blog.51cto.com/720558/144930