我知道这个话题已经好几次了,但我仍然坚持一点.我需要编写一个模拟cmd1 | cmd2 | cmd3 ...
管道的程序.
我的代码在这里:http://ideone.com/fedrB8
#include#include #include #include 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
Dipto.. 5
不是专家,但似乎以下问题是:
((close(fd[1]) == -1) || (close(in_fd) == - 1))
尽量不要在in_fd
那里关闭.
我认为,父母试图关闭由孩子关闭的同一个fd.
使用时,dup2()
您不需要关闭文件,因为dup2()
已经关闭文件.