我知道这个话题已经出现好几次了,但是我仍然停留在某一点。我需要编写一个模拟cmd1 | cmd2 | cmd3 ...管道的程序。
cmd1 | cmd2 | cmd3 ...
我的代码在这里: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
不是专家,但似乎以下几行是问题所在:
((close(fd[1]) == -1) || (close(in_fd) == - 1))
尽量不要在in_fd那里关闭。
in_fd
我认为,父母正在尝试关闭与孩子同样的fd。 使用时,dup2()您不需要关闭文件,因为dup2()已经关闭了文件。
dup2()