管道将一个程序的stdout重定向到另一个程序的stdin

时间:2017-03-03 22:36:06

标签: c exec piping

我们必须编写一个C程序,它将使用管道将一个命令/程序的stdin重定向到另一个命令/程序stdout。如果命令行上的程序已通过./a.out ls -l \; more,则应将ls -l的stdout重定向到more\;为分隔符。此程序适用于我们路径中的任何命令/程序,因此:./a.out cat filename.c \; more应与键入:cat filename.c | more相同。

我的问题是我的程序似乎无法正常执行或管道没有按预期工作。基本上我只是在我放置的print语句调试之外没有输出。具体来说,程序打印:Exec ...然后是ERROR,它都在父代码中。

  #include <fcntl.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <unistd.h>
  #include <sys/types.h>
  #include <sys/wait.h>
  void pipeit(char * pro1, char * pro2, char * p1args[], char * p2args[])
  {
     pid_t pid;
     int fd[2];
     int st;
     pipe(fd);
     pid = fork();

     if(pid < 0)
     {
        printf("Error Forking...\n");
        exit(-1);
     }
     else if(pid == 0)
     {
        dup2(fd[1],1);
        close(fd[0]);
        close(1);
        printf("Exec 1...\n");
        execv(pro1, p1args);
        printf("ERROR\n");
     }
     else
     {
        waitpid(pid,&st,0);
        if(st<0)
        {
           printf("Child Error\n");   
        }
        dup2(fd[0],0);
        close(fd[1]);
        close(0);
        printf("Exec...\n");
        execv(pro2,p2args);
        printf("ERROR\n");
     }
     return;
  }
  /* THIS IS JUST COMMAND LINE PARSING */
  int main(int argc, char * argv[])
  {
     int i = 1;
     char * pro1;
     char * pro2;
     char * first[argc+1];
     char * second[argc+1];
     while(i<argc && argv[i][0] != ';')
     {
        if(i == 1)
        {
           pro1 = argv[i];
        }
        else
        {
           first[i] = argv[i];
        }
        i++; 
     }
     first[i] = NULL;
     while(i<argc)
     {
        if(argv[i][0] == ';')
        {
           i++;
           pro2 = argv[i];
        }
        else
        {
           second[i] = argv[i];
        }
        i++; 
     }
     second[i] = NULL;
     pipeit(pro1,pro2,first, second);
     return 0;
  }

1 个答案:

答案 0 :(得分:0)

在孩子身上,你有:

    dup2(fd[1],1);
    close(fd[0]);
    close(1);

这会将管道复制到标准输出,但随后关闭标准输出。通过不关闭标准输出并关闭管道的两端来修复。经验法则:如果将管道的一端复制到标准输入,输出或错误,则应关闭两个原始管道描述符。

    dup2(fd[1],1);
    close(fd[0]);
    close(fd[1]);

父级中存在类似问题,标准输入已关闭。

您还有wait()错误的地方。进程必须同时运行。如果管道中的第一个进程生成了大量数据,而管道无法将其全部保存,则该进程将阻塞。如果另一个进程在读取任何内容之前等待第一个进程死亡,那么它将无法正常工作。