当我的命令为"-"
并启动一个新的Ruby解释器时,我试图理解IO.popen。
关于这个主题的材料并不多,我慢慢地通过它们,主要是因为我,因为我只是为了好玩而编码。
据我所知,IO.popen("-", "w+") {|f| ...}
被调用时 - 带有一个块 - 该块将由两者运行父进程和子进程。不同之处在于父进程将获得一个IO对象,但子进程只有Nil。这很简单,我需要检查块中的|f|
,当它是Nil时,执行是在子进程中,当它不是nil时,执行在父进程中。因此,我必须为if
分隔的父和子代码编写。
这一次有助于我理解这个问题,该块是IO.popen命令的一部分。
我有这段代码:
pipe = IO.popen("-","w+")
# puts "This line will break functionality if uncommented"
if pipe != nil then
pipe.puts "PID: #{Process.pid}"
$stderr.puts "Parent from child: #{pipe.gets.chomp}"
else
$stderr.puts "Child PID: #{Process.pid} and Parent #{gets.chomp}"
puts "M'kay"
end
pipe = IO.popen...
命令不应与if..else..end
块相关,但它们是。{1}}。对我来说,pipe
是一个文件句柄(就像在旧的Turbo Pascal中一样),它首先在某处定义,然后在别处操作。答案 0 :(得分:2)
没有人决定首先运行哪个进程。子进程可以先运行 - 或者父进程可以先运行 - 操作系统可以按任意方式安排它们。
这意味着父进程可以在子进程完成之前完成。当父进程完成时,它的管道被关闭,当子进程写入它时,它会得到一个异常。这就是你的代码中发生的事情。
为什么没有评论线就不会发生?在父进程中调用gets
时,它会一直等到子进程向管道写入一行。这意味着在孩子将一条线写入管道之前父母不会完成,这忽略了问题。但是,当您打印两行时,父进程在子项执行第二次 puts "M'kay"
之前终止的几率。
请尝试以下代码:
pipe = IO.popen("-","w+")
puts "This line will not break functionality"
puts "This line will not break functionality"
puts "This line will not break functionality"
if pipe != nil then
pipe.puts "PID: #{Process.pid}"
while line = pipe.gets
$stderr.puts "Parent from child: #{line.chomp}"
end
else
$stderr.puts "Child PID: #{Process.pid} and Parent #{gets.chomp}"
puts "M'kay"
end
它等待孩子关闭管道(然后pipe.gets
将返回nil
),然后它会终止,并且它确保它不会再尝试在那里写。