为什么当程序等待 stdin 时 open4 无法从 stdout 读取数据?
我正在使用 open4 gem,但从生成的进程标准输出读取时遇到问题。我有一个 ruby 程序,test1.rb
:
print 'hi.' # 3 characters
$stdin.read(1) # block
同一目录中的另一个 ruby 程序,test2.rb
:
require 'open4'
pid, stdin, stdout, stderr = Open4.popen4 'ruby test1.rb'
p stdout.read(2) # 2 characters
当我运行第二个程序时:
$ ruby test2.rb
它永远坐在那里,没有打印任何东西。为什么会发生这种情况?我可以采取什么措施来阻止这种情况?
I am using the open4
gem and having problems reading from the spawned processes stdout. I have a ruby program, test1.rb
:
print 'hi.' # 3 characters
$stdin.read(1) # block
And another ruby program in the same directory, test2.rb
:
require 'open4'
pid, stdin, stdout, stderr = Open4.popen4 'ruby test1.rb'
p stdout.read(2) # 2 characters
When I run the second program:
$ ruby test2.rb
It just sits there forever without printing anything. Why does this happen, and what can I do to stop it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我需要将
test1.rb
更改为此。我不知道为什么。I needed to change
test1.rb
to this. I don't know why.默认情况下,您
打印
到 stdout 或其他文件的所有内容都会写入 Ruby 的缓冲区(或位于 Ruby 下的标准 C 库)。如果发生以下事件之一,缓冲区的内容将转发到操作系统:flush
。对于其他文件,也会在其他情况下执行
flush
,例如ftell
。如果将 stdout 置于无缓冲模式 (
$stdout.sync = true
),则不会使用缓冲区。默认情况下,stderr 是无缓冲的。
进行缓冲的原因是效率:将输出数据聚合在缓冲区中可以节省许多系统调用(对操作系统的调用)。系统调用非常昂贵:它们需要数百甚至数千个 CPU 周期。通过一些代码和用户空间中的一些缓冲区来避免它们会带来很好的加速。
关于缓冲的好读物:为什么 printf 在调用后不会刷新,除非格式字符串中有换行符?
By default, everything that you
print
to stdout or to another file is written into a buffer of Ruby (or the standard C library, which is underneath Ruby). The content of the buffer is forwarded to the OS if one of the following events occurs:flush
explicitly.For other files, a
flush
is done on other occasions, too, likeftell
.If you put stdout in unbuffered mode (
$stdout.sync = true
), the buffer will not be used.stderr is unbuffered by default.
The reason for doing buffering is efficiency: Aggregating output data in a buffer can save many system call (calls to operating system). System calls are very expensive: They take many hundreds or even thousands of CPU cycles. Avoiding them with a little bit of code and some buffers in user space results in a good speedup.
A good reading on buffering: Why does printf not flush after the call unless a newline is in the format string?
我不是流程方面的专家。
从我第一眼看到API文档来看,open4的使用顺序是这样的:
首先将文本发送到标准输入,然后关闭标准输入,最后从标准输出读取文本。
所以。你可以像这样
test2.rb
I'm not an expert in process.
From my first sight of API document, the sequence of using open4 is like this:
first send text to stdin, then close stdin and lastly read text from stdout.
So. You can the
test2.rb
like this