Linux学习笔记-使用管道通信实现cat /etc/passwd | grep root这条命令

子进程1:
执行命令将执行结果写入管道

子进程2:
从管道中读取命令执行的结果,然后根据关键字过滤

如 cat /etc/passwd | grep root这条命令

Linux学习笔记-使用管道通信实现cat /etc/passwd | grep root这条命令

注意以下几点:
1.指针数组构建参数列表;
2.匿名管道,通常是指有关系的进程;
3.fork()函数的返回值大于0说明是父进程;
4.子进程创建完,要break下,不然会出现进程链;
5.父进程要等子进程创建完成后再回收;
6.cat命令的默认输出是标准输出(屏幕);
7.在本程序中将标准输出重定向到管道写端(调用dup2函数【dup to XXX】);
8.grep命令默认读取的内容来源标准输入。

 

源码如下:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.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 error");
                exit(1);
        }       

        pid_t pid;
	int i = 0;
        for(; i < 2; i++){

                pid = fork();
                if(pid < 0){

                        perror("fork error");
                        exit(1);
                }
                else if(pid == 0){	//child process

			if(i == 0){
				//第一个进程负责往管道写
				close(fd[0]);	//关闭读端

				//将标准输出重定向到管道写端
				if(dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO){
		
					perror("dup2 error");
				}
				close(fd[1]);

				//调用exec函数执行cat命令
				if(execvp(cmd1[0], cmd1) < 0){
				
					perror("execvp error");
					exit(1);
				}
				break;
			}
			if(i == 1){
				//第二个进程负责往管道读
				close(fd[1]);	//关闭写端

				//将标准输出重定向到管道的读端
				if(dup2(fd[0], STDIN_FILENO) != STDIN_FILENO){

					perror("dup2 error");
				}
				close(fd[0]);
				
				//调用exec函数执行grep命令
				if(execvp(cmd2[0], cmd2) < 0){
				
					perror("execvp error");
					exit(1);
				}
				break;
			}		
		}
		else{		//parent process
		
			if(i == 1){
				
				//父进程要等子进程全部创建完再收回
				close(fd[0]);
				close(fd[1]);
				wait(0);
				wait(0);
			}	
		}
	}
	exit(0);
}

程序运行截图如下:

Linux学习笔记-使用管道通信实现cat /etc/passwd | grep root这条命令