C Minishell - 需要杀死僵尸进程以实现管道功能

3

我正在使用C语言(用于Unix)构建一个迷你shell。我刚刚弄懂了如何使管道运作,但是我遇到了僵尸问题。假设我有以下代码:

echo a | echo b | echo c

这段代码没有输出任何内容,实际上应该输出"c"。但是,如果我告诉我的shell去执行每个子命令,然后在继续下一个命令之前等待一段时间,它就可以正常工作。然而,这不是一个真正的解决方案,因为我希望得到管道之间自然协调的效果,而不是等待。
我遇到了一个问题,无法有效地等待所有僵尸进程,一旦最后一个命令被执行。我尝试在最后一个执行之后,但shell退出之前做到这一点:
while(waitpid(-1, NULL, WNOHANG) > 0);

然而,没有运气。到目前为止,唯一有效的方法是告诉我的 shell 执行每个子命令,然后等待再开始下一个命令。这是整个主 shell 文件: http://pastebin.com/YV96mFy7 处理输入的主要函数(processline())从第105行开始。感谢你们的帮助,如果需要更多信息,请随时提出。

1
你知道 WNOHANG 应该做什么吗?是的,这是错误的。你应该 (a) 捕获 SIGCHLD 并在那里等待;或者 (b) 知道你有多少子进程,等待完全相应数量的子进程退出而不使用 WNOHANG。 - J-16 SDiZ
哦,我该如何捕获SIGCHLD信号?我只需在父进程中创建一个处理程序,然后等待接收到SIGCHLD信号时执行吗?如果是这样,那么WNOHANG参数与此有什么关系呢?谢谢 :) - robins35
通常情况下,您不能等待进程1完成后再启动进程2。您可能会在C Minishell-添加管道中找到一些帮助。 - Jonathan Leffler
那是我的帖子,哈哈,我刚才用第二个账号发的。我看到你添加了更多的东西,我会去看一下的。 - robins35
1个回答

4

更改这个

while(waitpid(-1, NULL, WNOHANG) > 0);

致:

while(wait(NULL) > 0);

/* which is equivalent to */
while(waitpid(-1, NULL, 0) > 0);

如果您不想阻塞父进程,可以捕获 SIGCHLD 信号,然后在信号处理程序中调用 wait() 来等待所有子进程完成。

这将导致父进程等待所有子进程完成。


你说的话不是真心的吧,我想。你在第二个循环中打算使用普通的wait()吗?waitpid()需要三个参数,但是waitpid(-1, 0, 0)wait(0)是相同的,我认为。 - Jonathan Leffler
@JonathanLeffler 是的,那正是我想表达的,我复制了这行代码但忘记将其更改为 wait,谢谢。 - iabdalkader

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接