我正在编写自己的shell。以下是其中的一部分。我想用两个子进程实现管道。 但是当我执行下面的代码时,一些命令可以工作,有些则没有。 '谁|排序','ls |排序'工作,但'll | sort','cat file |排序'让我的shell停止。我必须'cntrl + c'才能从我的shell中逃脱。我不明白为什么有些命令有效,有些则不然。请有人指出我错过了什么?
int pipefd[2];
int pipePos = checkPipePos(argc, argv); //find '|' command position in argv
if (pipe(pipefd) == -1) {
printf("Creating pipe failed\n");
return;
}
if (fork() == 0) {
close(pipefd[0]);
dup2(pipefd[1], 1);
execlp(argv[0], argv[0], NULL);
}
if (fork() == 0) {
close(pipefd[1]);
dup2(pipefd[0], 0);
execlp(argv[pipePos + 1], argv[pipePos + 1], NULL);
}
close(pipefd[0]);
close(pipefd[1]);
while (wait(NULL) >= 0);
答案 0 :(得分:1)
我在这里看到一个可能的问题,可能会或可能不会解释非确定性结果。
在您的子进程中,在您复制其中一个管道文件描述符之后,您并未关闭原始文件描述符。
dup2(oldfd, newfd)
将oldfd
重复到newfd
,但oldfd
仍处于打开状态。 oldfd
和newfd
文件描述符现在都指向同一个文件。请参见dup2手册页。
通常,在使用dup2()文件描述符之后,您将要关闭()oldfd
。
那么,这里要发生的是,其中一个子进程在stdout
和其他一些随机文件描述符上具有相同的文件描述符,而另一个子进程将拥有与stdin
相同的情况。
这可能会也可能不会导致问题,具体取决于子进程的功能。真的不能说肯定,但你肯定想解决这个问题,看看它是否有帮助。
答案 1 :(得分:0)
你的管道逻辑是正确的。
ll | sort
不起作用,因为ll
不是可执行文件。
cat file | sort
不起作用,因为您没有传递file
参数。
Sam Varshavchik的改进是有效的。这是一个很好的修复,但它不会导致任何严重的问题。所有这一切导致浪费一个文件描述符插槽。