【问题标题】:Ruby IO.popen with "-" , what happens under the hood?Ruby IO.popen 带有“-”,引擎盖下会发生什么?
【发布时间】:2011-08-02 11:25:43
【问题描述】:

当它的命令是 "-" 时,我试图理解 IO.popen,它启动了一个新的 Ruby 解释器。

关于这个主题的资料不多,我慢慢地了解它们,主要是因为我只是为了好玩而编写代码。

据我所知,当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

问题:

  • 是什么决定了哪个进程首先运行?如果他们要附加一个文件,它是否容易受到竞争条件的影响?
  • 为什么第 2 行代码中断? pipe = IO.popen... 命令不应该与 if..else..end 块相关,但它们是。对我来说,pipe 是一个文件句柄(就像在旧的 Turbo Pascal 中一样),它首先在某个地方定义,然后在其他地方进行操作。

【问题讨论】:

    标签: ruby io subprocess popen ruby-1.9.2


    【解决方案1】:

    没有人决定哪个进程首先运行。子进程可以先运行——或者父进程可以先运行——操作系统可以以任何一种方式调度它们。

    这意味着父进程可能在子进程完成之前完成。当父进程完成时,它的管道被关闭,当子进程写入它时,它会得到一个异常。这就是您的代码中发生的情况。

    为什么没有注释行就不会发生?当您在父进程中调用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),然后它会终止,并确保它不会再尝试在那里写。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-08
      • 2019-05-12
      • 2019-04-07
      • 2010-11-03
      • 2023-03-06
      • 2020-01-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多