【问题标题】:How do I allow two concurrent processes to communicate?如何允许两个并发进程进行通信?
【发布时间】:2010-10-17 06:48:47
【问题描述】:

我有两个独立的进程:一个 C 程序,它每秒输出逗号分隔的值,后跟一个换行符,一个 Perl 程序,它接受数据(以相同格式)并处理这些数据。

C 程序输出(通过 printf)值如下:

1, 2, 3, 4, 5, 6  
7, 8, 9, 10, 11, 12  
...

Perl 程序处于无限循环中,等待 STDIN 以处理这些数据:

while ($line = <STDIN>)
{
    chomp($line) # Line should now read "1,2,3,4,5,6"
    # Process data
}

我希望这两个进程实时通信。标准 bash 管道不起作用(例如 process1 | process2),因为 Perl 程序在处理输入之前等待第一个程序完成。

是否有人对此问题的解决方案有任何想法、建议或见解?提前谢谢!

【问题讨论】:

  • 严格来说,这与“实时”无关
  • 你说得对,我写的很匆忙,想不出更好的方法来解释我希望这些过程如何工作。并发可能是更好的选择。
  • 并发好多了,还有一个编辑按钮供你修复。

标签: c perl pipe


【解决方案1】:

管道应该没问题;您只需要控制何时刷新 C 程序的输出以使其可用于 perl 脚本。您可以在 C 程序中使用 fflush() 执行此操作,这将强制从您的 C 程序中推出缓冲区,以便 perl 程序可以读取它。

管道本身没有任何东西会导致 perl 程序在处理其输出之前等待 C 程序完成写入。你的 perl 程序被编写成一次处理 STDIN 一行:

while ($line = <STDIN>) { ... }

&lt;&gt; 在这种情况下从STDIN 读取一行,但如果没有可用的,它将阻塞直到有。从 C 程序调用 fflush() 将实现这一点。

看看Wikipedia article on Pipelines。实现部分简要描述了管道是如何缓冲的,这将有助于您了解进程的通信方式。管道确实允许进程之间的并发,并且从管道读取和写入管道的进程由调度程序管理,就像其他进程一样。您的问题在于缓冲。

【讨论】:

  • 我认为 C 程序在打印换行符时会刷新所有输出。
  • 你的回答是对的——我什至探索过 fflush 但我从没想过在标准输出上使用它。由于 perl 程序行为的性质,我误以为它在 c 程序上“等待”。我在我的 printf 语句之后添加了 fflush(stdout) 并且它完美地工作!谢谢!!
  • @Chris Lutz,自动刷新仅在流处于行缓冲模式时才会发生,这通常仅在流在 tty 上打开时才会发生。一旦 stdout 成为管道,它默认为完全缓冲以获得最佳性能。
【解决方案2】:

C 程序应该明确地 fflush() 它的输出缓冲区,或者使用 pty.后者更笨拙,但使 C 代码更简单。如果您不熟悉,请尝试“man 3 fflush”。

【讨论】:

  • 使用 pty 太过分了;如果在 C 代码中使用 stdio,则刷新输出很重要(如果直接使用 write(),则不重要)。
  • 只有当两个进程必须交互时才需要一个 pty,并且只有当一个或两个进程必须忘记将非人类作为交互方时才需要。 Ptys 在类 unix 平台之外也不是很便携。
  • 我同意 pty 是矫枉过正,但它欺骗 C 程序在每个换行符后自动刷新。从这个意义上说(并且仅在这个意义上!)它使 C 程序更简单,但牺牲了更复杂的环境。
猜你喜欢
  • 1970-01-01
  • 2016-03-27
  • 1970-01-01
  • 2017-06-06
  • 2013-02-24
  • 1970-01-01
  • 2020-05-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多