shell命令的本质是一个个封装好的c函数,同样由基本系统调用编写。
相当于shell行输入:cat /etc/passwd | grep root,需要任何过滤功能,只需要将传入字符串改变即可。
/*************************************************************************
> File Name: cmd_pipe.c
> Author: CC
> Mail: 6828620@163.com
> Created Time: 2018年09月08日 星期六 15时39分41秒
************************************************************************/
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<wait.h>
char *cmd1[3] = {
"/bin/cat",
"/etc/passwd",
NULL
};
char *cmd2[3] = {
"/bin/grep",
"root",
NULL
};
int main(void)
{
int fd[2];
if(pipe(fd) < 0){
perror("pipe create error!\n");
exit(1);
}
//创建进程扇
int i = 0;
pid_t pid;
for(i=0; i<2; i++){
pid = fork();
if(pid < 0){
perror("fork error!\n");
}else if(pid == 0){
//child
if(i == 0){
//child 1 pipe write
//close read
close(fd[0]);
/*将标准输出重定向到管道的写端,而不是输出到屏幕*/
if(dup2(fd[1],STDOUT_FILENO) != STDOUT_FILENO){
perror("dup2 error!\n");
}
//已经复制了一份给标准输出,所以可以关掉fd
close(fd[1]);
//调用exec函数执行cat
if(execvp(cmd1[0],cmd1) < 0){
perror("execvp error!\n");
exit(1);
}
break;
}
if(i == 1){
//child 2 pipe read
//close write
close(fd[1]);
//grep默认读取路径是标准输入,所以要改变为管道的读端
if(dup2(fd[0],STDIN_FILENO) != STDIN_FILENO){
perror("dup2 error!\n");
}
//同上,可以关闭
close(fd[0]);
//调用exec函数执行grep
if(execvp(cmd2[0],cmd2) < 0){
perror("execvp error!\n");
exit(1);
}
break;
}
}else{
//parent父进程必须等到子进程全部创建完毕才去回收。
if(i == 1){
close(fd[0]);
close(fd[1]);
wait(0);
wait(0);
}
}
}
return 0;
}