管道如何工作?如果我通过CLI运行程序并将输出重定向到文件,我可以将该文件传输到另一个程序中吗?
基本上,当一行被写入文件时,我希望它能够立即传送到我的第二个应用程序(我试图从现有程序中动态绘制图形)。在转到下一个命令之前,只是不确定管道是否完成了第一个命令。
非常感谢任何反馈!
答案 0 :(得分:56)
如果你想将一个程序的输出重定向到另一个程序的输入,只需使用一个简单的管道:
program1 arg arg | program2 arg arg
如果您想将program1
的输出保存到文件中并将其保存到program2
,您可以使用tee(1)
:
program1 arg arg | tee output-file | program2 arg arg
管道中的所有程序都是同时运行的。大多数程序通常使用阻止 I / O:如果他们试图读取他们的输入而没有任何东西,他们阻止:也就是说,他们停止了,操作系统de - 安排它们运行,直到有更多输入可用(以避免吃掉CPU)。类似地,如果管道中较早的程序写入数据的速度比后来的程序读取的速度快,那么管道的缓冲区最终会填满并且编写器阻塞:操作系统将其解除调度,直到管道的缓冲区被读取器清空,然后它可以继续写作。
修改强>
如果要使用program1
的输出作为命令行参数,可以使用反引号或$()
语法:
# Runs "program1 arg", and uses the output as the command-line arguments for
# program2
program2 `program1 arg`
# Same as above
program2 $(program1 arg)
$()
语法应该是首选,因为它们更清晰,并且可以嵌套。
答案 1 :(得分:26)
管道在运行第二个之前未完成第一个命令。 Unix(和Linux)管道同时运行所有命令。如果
,命令将被暂停缺乏投入。
它产生的产量远远超过其后续产品的消费量。
对于大多数程序,输出是缓冲,这意味着OS在将其传递到管道的下一个阶段之前会累积大量输出(可能大约8000个字符)。此缓冲用于避免在进程和内核之间来回切换太多。
如果您希望立即发送管道上的输出,您可以使用无缓冲 I / O,在C中意味着调用类似fflush()
的内容以确保任何缓冲输出是立即发送到下一个进程。无缓冲输入也是可能的,但通常是不必要的,因为缺乏输入的进程通常不会等待完整缓冲区,但会处理您可以获得的任何输入。
对于典型应用,不建议使用无缓冲输出;通常使用默认值获得最佳性能。但是,在您的情况下,您希望立即执行动态绘图,第一个进程具有可用信息,您肯定希望使用无缓冲输出。如果你正在使用C,那么只要你想要输出就调用fflush(stdout)
就足够了。
答案 2 :(得分:9)
如果您的程序正在使用stdin
和stdout
进行通信,请确保在编写后调用fflush(stdout)
或找到某种方法来禁用标准IO缓冲。我能想到的最佳参考实际上描述了如何在C / C ++中最好地实现管道是Advanced Programming in the UNIX Environment或UNIX Network Programming: Volume 2。你也许可以从this article开始。
答案 3 :(得分:3)
如果您的两个程序坚持读取和写入文件而不使用stdin / stdout,您可能会发现可以使用命名管道而不是文件。
使用mknod(1)命令创建命名管道:
$ mknod /tmp/named-pipe p
然后将程序配置为读取和写入/ tmp / named-pipe(使用您认为合适的路径/名称)。
在这种情况下,两个程序将并行运行,当管道变为满/空时根据需要阻塞,如其他答案中所述。