Linux操作系统 - 父,子,父进程的输入输出管道

时间:2016-02-27 15:56:10

标签: c linux bash shell

我有一些名为c-shell的C代码可以执行以下操作。父c-shell读入Linux命令行,并强制子进程执行该命令。在收到来自父级的信号表明它已准备好执行之前,子进程不会执行命令。它可以处理输入文件以提供命令参数,也可以从命令行读取它们。它可以处理将输出发送到输出文件,而不仅仅是将执行的命令输出打印到stdout。它将输出发送到输出文件的方式是由子进程将它的stdout重定向到管道,并且一旦收到子进程完成运行的sig-child信号,父进程就会从该管道读取。它可以处理多个命令(在命令之间放置一个分号)。它可以处理第一个命令的管道输出到命令行中的第二个命令。但是 - 这是我的问题 - 它无法处理一个命令,其中管道输出一个命令作为第二个命令的输入,然后将第二个命令的输出发送到输出文件。考虑到以上所有案例的完美运作,我感到很困惑。我可以在完成后将已执行子进程的输出重定向到父进程,以便完成它。我可以将运行的第一个命令的输出重定向为第二个运行命令的输入。但是,如果我尝试将输出发送到输出文件的第二个命令,我就不能这样做。如果这个问题没有意义,我会发布更多细节。

例如:如果我在c-shell中输入以下命令行:ls -l | grep lsOut(意思是,我做一个详细的目录列表,并在该目录列表输出中,有一些文件包含字符," lsOut"(从ls命令输出文件),grep命令应该过滤掉目录列表中不包含这些字符的所有其他文件。当它打印到stdout时工作正常。当我执行命令如:ps> psOut时,ps命令的输出写入psOut文件没有问题。但是,如果我执行命令:ls -l | grep lsOut> lsOutFile,会发生什么令人困惑。它将第一个命令ls -l打印到stdout,虽然我在print语句中看到第二个命令,grep lsOut正在运行,并且应该从ls -l接收输出作为grep lsOut的输入,它似乎没有任何影响。唯一的输出是整个ls -l目录,没有grep过滤,虽然它说它将它写入输出文件,它不会到达那里。如果你想让我发布一个链接到cod e,我可以做到。非常感谢你!我花了好几个小时试图调试这个问题。

1 个答案:

答案 0 :(得分:0)

  

它将输出发送到输出文件的方式是由孩子   将它的标准输出重定向到管道,父节点从该管道读取   一旦它收到子进程完成的sig-child信号   运行

把它抱在这里。俗话说:不要通过“去”。不要收200美元。

这部分已经不太对了。如果子进程开始喷出足够数量的输出,那么你最终会同时拥有一个挂起的父进程和一个挂起的子进程。

管道缓冲区的大小不受限制。管道缓冲区具有固定的上部最大内部大小。我的回忆是默认的管道缓冲区大小是8,192字节。它实际上可能是其他东西,但实际大小并不重要。无论管道缓冲区大小是什么,一旦缓冲区填满,写入管道缓冲区的进程就会进入休眠状态,直到读取进程开始通过读取来清空管道。只要读者和作者处理独立工作,一个人的阅读,一个人的写作,一切都顺利进行。如果编写器的写入速度比读者读取的速度快,一旦未读字符的数量达到管道的最大大小,内核就会静静地将编写器进程置于write()内,直到读者赶上。

如果父进程在开始从stdout管道读取之前等待子进程退出,并且子进程写入超过8,192(或者实际大小为)的字节数,则子进程将在其中暂停{ {1}}调用,直到管道读取。并且由于父进程在子进程终止之前不会从管道中读取,因此两个进程将永远等待彼此。

因此,我们已经知道您的应用程序未正确处理此情况。虽然您已经描述了与应用程序稍有不同的问题,但鉴于应用程序没有正确处理进程间管道语义,很可能您的实际问题(如果不是这样)与之密切相关。

您必须完全重新设计应用程序如何正确实现进程间管道。