I/O重定向和管道:使用pipe、fork、exec详解。

要使who|sort用程序实现,需进行I/O重定向,参考了Unix/Linux编程实践教程,画了几个图来理解这个程序,可能会更好。

1.      当运行pipe(pipe_id)以及fork之后,父进程和子进程共享stdin、stdout和管道,如图所示:


2. 我们知道,可以设定子进程写,父进程读,也就是子进程执行who程序,通过写管道口,输出到父进程的读管道口(这是没有重定向的情况),于是万恶的重定向来了,他告诉你可以进入管道,但是不是常规的那个门口进入,而是从另外一个门进入。但是管道还是管道,只是进出口不同而已,你懂得。

第一步:关闭子进程的读管道口

第二步:关闭子进程输出流


第三步:复制子进程写管道口


第四步:关闭子进程写管道


至此,成功实现子进程写管道口角色的转换,于是在子进程执行程序,执行比如who时,他以为他输出到标准输出流,其实他已经输出到了些管道口。

3. 同理,对父进程进行一系列类似的处理

至此成功实现角色转换!

代码

  1. #include "../apue.h"  
  2.   
  3. int main(int argc, char *argv[])  
  4. {  
  5.     int pid, pipe_id[2], newfd;  
  6.     if(argc != 3)  
  7.         oops("usage: cmd need 3 paraments", 1);  
  8.           
  9.     if(pipe(pipe_id) 
  10.         oops("pipe", 1);  
  11.           
  12.     if((pid = fork()) 
  13.     {  
  14.         oops("fork", 1);  
  15.     }  
  16.     else if(pid == 0)           ///子进程负责写  
  17.     {  
  18.         close(pipe_id[0]);  
  19.         if(dup2(pipe_id[1], 1) == -1)  
  20.             oops("dup2", 1);  
  21.           
  22.         close(pipe_id[1]);  
  23.         execlp(argv[1], argv[1], NULL);  
  24.         oops("execlp", 2);  
  25.     }  
  26.     else                        ///父进程负责读  
  27.     {     
  28.         close(pipe_id[1]);  
  29.         if(dup2(pipe_id[0], 0) == -1)  
  30.             oops("dup2", 1);  
  31.           
  32.         close(pipe_id[0]);  
  33.         execlp(argv[2], argv[2], NULL);  
  34.         oops("execlp", 1);  
  35.     }  
  36.     exit(0);  

save file as pipe_fork_exec.c

compile and how to run from command line

#gcc pipe_fork_exec.c

#./a.out ls sort

#./a.out ls wc

12-14 12:01