再次在Unix中recursionpipe道

我知道这个话题已经有好几次了,但是我仍然坚持一点。 我需要编写一个模拟cmd1 | cmd2 | cmd3 ...的程序 cmd1 | cmd2 | cmd3 ... cmd1 | cmd2 | cmd3 ...pipe道。

我的代码在这里: http : //ideone.com/fedrB8

 #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <stdlib.h> void pipeline( char * ar[], int pos, int in_fd); void error_exit(const char*); static int child = 0; /* whether it is a child process relative to main() */ int main(int argc, char * argv[]) { if(argc < 2){ printf("Usage: %s option (option) ...\n", argv[0]); exit(1); } pipeline(argv, 1, STDIN_FILENO); return 0; } void error_exit(const char *kom){ perror(kom); (child ? _exit : exit)(EXIT_FAILURE); } void pipeline(char *ar[], int pos, int in_fd){ if(ar[pos+1] == NULL){ /*last command */ if(in_fd != STDIN_FILENO){ if(dup2(in_fd, STDIN_FILENO) != -1) close(in_fd); /*successfully redirected*/ else error_exit("dup2"); } execlp(ar[pos], ar[pos], NULL); error_exit("execlp last"); } else{ int fd[2]; pid_t childpid; if ((pipe(fd) == -1) || ((childpid = fork()) == -1)) { error_exit("Failed to setup pipeline"); } if (childpid == 0){ /* child executes current command */ child = 1; close(fd[0]); if (dup2(in_fd, STDIN_FILENO) == -1) /*read from in_fd */ perror("Failed to redirect stdin"); if (dup2(fd[1], STDOUT_FILENO) == -1) /*write to fd[1]*/ perror("Failed to redirect stdout"); else if ((close(fd[1]) == -1) || (close(in_fd) == - 1)) perror("Failed to close extra pipe descriptors"); else { execlp(ar[pos], ar[pos], NULL); error_exit("Failed to execlp"); } } close(fd[1]); /* parent executes the rest of commands */ close(in_fd); pipeline(ar, pos+1, fd[0]); } } 

对于最多3个命令来说,它是完全正常的,但是对于4个或者更多的命令来说,这个命令是完全正确的,经过几个小时的分析,我仍然无法得到问题所在。

 Example: ./prog ls uniq sort head gives: sort: stat failed: -: Bad file descriptor 

Solutions Collecting From Web of "再次在Unix中recursionpipe道"

不是专家,但似乎下面的线是问题:

 ((close(fd[1]) == -1) || (close(in_fd) == - 1)) 

尽量不要在那里关闭in_fd

我想,父母正试图关闭由孩子关闭的同一个fd。
当你使用dup2()你不需要关闭文件,因为dup2()已经关闭了文件。