不能管道少(1)

时间:2013-04-23 16:07:58

标签: c unix

我正在尝试编写一个应该用作“printenv | sort | less”的程序。然而,最后一个管道减少不起作用。我可以使用预期的结果来管道cat(显示环境变量),但是当我管道更少时,不会显示任何内容。程序运行较少但没有任何反应。如果我更多地使用该程序,则将输出捕获到窗口底部,之后没有任何反应。我不是寻呼机。

有什么想法吗?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>

#define WRITE 1
#define READ 0

#define DEBUG 1

int p1[2], p2[2], p3[2];

void err(char* msg){
  perror(msg);
  exit(EXIT_FAILURE);
}

void closePipe(int pipeEnd[2]){

  if (close(pipeEnd[READ]) == -1)
    err("error when closing pipe, read");

  if (close(pipeEnd[WRITE]) == -1)
    err("error when closing pipe, write");
}

int main(int argc, char** argv, char** envp){

  int pid1, pid2, pid3;


  /*Creating pipes*/
  if (pipe(p1) == -1){
    err("pipe1");
  }
  if (pipe(p2) == -1){
    err("pipe2");
  }

  /*
  if (pipe(p3) == -1){
    err("pipe3");
  }
  */

  /*First fork*/
  pid1 = fork();
  if (pid1 == -1){
    err("fork1");
  }

  /**FIRST CHILD*************PRINTENV****************/
  else if (pid1 == 0){ 

    if (dup2(p1[WRITE],STDOUT_FILENO)== -1){
      err("dup2 miss");
    }

    closePipe(p2);
    closePipe(p1);

    if (execlp("printenv", "printenv", NULL) == -1){
      err("execlp printenv does not like you!");
    }
  }

  /**PARENT*******************************************/
  else {

    pid2 = fork();
    if (pid2 == -1){
      err("fork2");
    }

    /**SECOND*CHILD***********SORT*******************/
    else if (pid2 == 0){

      if (dup2(p1[READ],STDIN_FILENO) == -1){
    err( "dup2 p1 read" );
      }
      if (dup2(p2[WRITE], STDOUT_FILENO) == -1){
    err("dup2 p2 write");
      }

      closePipe(p2);
      closePipe(p1);

      if (execlp("sort", "sort", NULL) == -1){
    err("execlp sort does not like you!");
      }
     }

    /**PARENT*****************************************/
    else {

      pid3=fork();
      if (pid3 == -1){
    err("fork3");
      }
      /**THIRD CILD***************LESS****************/
      else if (pid3 == 0){

    if (dup2(p2[READ], STDIN_FILENO) == -1){
      err("err dup2 read");
    }

    closePipe(p2);
    closePipe(p1);

    char *args4exec[] = {"less", NULL};

    if (execvp(args4exec[0], args4exec) == -1){
      err("err in exelp pager");
    }
      }
    }
  }  
  return 0;
}

1 个答案:

答案 0 :(得分:5)

两件事。首先,在父母中你还需要关闭管道。其次,您的父进程应该在退出之前等待less进程完成。尝试将其添加到您的代码中:

/* ... */

  closePipe(p1);
  closePipe(p2);
  waitpid(pid3, NULL, 0);

  return 0;
}

第一个问题导致孩子永远无法正确接收EOF,而第二个问题会导致less立即退出,因为父母会离开。