我决定编写一个简单的硬编码c程序来更好地理解管道是如何工作的。 该程序有3个命令: 找 。 -name' 。' | sed' s /.*。。|排序
它适用于1个管道(如果我只使用2个命令)但是它失败了2个管道(排序只是没有得到信息)。
我认为错误是关闭或waitpid,但我已经尝试了一切(我能想到)但它仍然无效。我错过了什么? 我使用的信息:
Is it possible to have pipe between two child processes created by same parent (LINUX, POSIX)
http://www.quora.com/Unix/How-can-I-write-a-code-for-PIPE-in-C-shell-script-python< - Sams例子
Implementation of multiple pipes in C
编辑: 命令写得没有错误。问题肯定不在其中(因为如果我只使用1个管道它们可以工作) 我的代码:
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
pid_t test, test2, test3;
int old_pipe[2];
int new_pipe[2];
//test command
//char *argv1[] = {"ls", "-1", "-h", NULL};
char *argv1[] = {"find", ".", "-name", "*.*",NULL};
char *argv2[] = {"sed", "s/.*\\.//", NULL};
char *argv3[] = {"sort", NULL};
//creates a pipe
pipe(old_pipe);
pipe(new_pipe);
test = fork();
if(test == 0){
dup2(old_pipe[1], 1);
close(old_pipe[0]);
execvp(argv1[0], argv1);
perror("exec");
return 1;
}
test2 = fork();
if(test2 == 0){
dup2(old_pipe[0], 0);
close(old_pipe[1]);
dup2(new_pipe[1], 1);
close(new_pipe[0]);
execvp(argv2[0], argv2);
perror("exec");
return 1;
}
test3 = fork();
if(test3 == 0){
dup2(new_pipe[0], 0);
close(new_pipe[1]);
execvp(argv3[0], argv3);
perror("exec");
return 1;
}
close(old_pipe[0]);
close(old_pipe[1]);
close(new_pipe[0]);
close(new_pipe[1]);
waitpid(test);
waitpid(test2);
waitpid(test3);
return 0;
}
答案 0 :(得分:1)
你的第3个执行官(开始“排序”)没有关闭old_pipe[1]
并保持打开状态。 sed
将无法看到EOF并保持活力。你应该很晚才打电话给pipe(2)
。
我建议调查/proc/<pid>/fd
resp。使用lsof
查看哪些文件描述符是打开的。例如。之后
dup2(old_pipe[1], 1);
close(old_pipe[0]);
如果不是old_pipe[1]
,则应关闭1
。
更多解释(如评论中所述):你的程序有
pipe(old_pipe);
pipe(new_pipe);
test = fork();
/* --> 'find'; writes into old_pipe[1] */
test2 = fork();
/* --> 'sed'; reads from old_pipe[0], writes into new_pipe[1] */
test3 = fork();
/* --> 'sort'; reads from new_pipe[0] */
只要输入(test2
)打开,old_pipe[0]
程序就不会退出。因为test3
(等待test2
完成)此管道处于活动状态,所以它将死锁。
关闭子分支中的fds不会在父进程中关闭它们。