【问题标题】:How do you spawn a child process in Ruby?如何在 Ruby 中生成子进程?
【发布时间】:2008-11-20 22:19:37
【问题描述】:

我想将我的主进程中的一段代码卸载到子进程以使其同时运行。我还想拥有生成的子进程的 PID,以便在必要时监视并杀死它。

【问题讨论】:

    标签: ruby


    【解决方案1】:

    除了 Chris 的出色回答外,请记住从您的主进程中调用 Process.wait 以获取您的子进程,否则您将留下僵尸。

    cmets 中要求的示例:

    pid = Process.fork do
      puts "child, pid #{Process.pid} sleeping..."
      sleep 5
      puts "child exiting"
    end
    
    puts "parent, pid #{Process.pid}, waiting on child pid #{pid}"
    Process.wait
    puts "parent exiting"
    

    【讨论】:

    • 甜,这是一个很棒的提示。
    • 您将 Process.wait 放在什么位置以及如何将 Process.wait 放在上面接受的答案中?
    • 请注意,不带参数的Process.wait 等待 any 子进程,因此在更一般的情况下,即使该特定子进程,此代码 sn-p 也会退出父进程以上不退出。更准确的版本会改为 Process.wait(pid)
    • 是否有独立于平台的方式来做到这一点(即没有fork,因为那只在Unix上)?
    • 让我们同意Process.waitall。父母将等到 ALL 孩子退出。
    【解决方案2】:

    您可以使用fork 内核方法。这是一个例子:

    #!/usr/bin/env ruby
    puts "This is the master process."
    
    child_pid = fork do
      puts "This is the child process"
      exit
    end
    
    puts "The PID of the child process is #{child_pid}"
    

    fork 方法返回它派生的进程的 PID,并执行传递的块中的任何代码。像常规的 Ruby 块一样,它保留了父进程的绑定。

    最好让你的分叉进程exit

    【讨论】:

    • 使用 Ruby 需要记住的一点是,并非所有事情在 Windows 和 *nix 中的工作方式都完全相同。有时它们在 Windows 上完全未实现,因此使用后果自负。
    • @Vadim 我认为这是一个特性,而不是一个错误。
    • 我对打电话给exit 有点困惑——为什么(或何时)需要它?
    • @skwisgaar exit 是确保分叉进程终止所必需的。否则,您最终可能会遇到僵尸或孤儿进程。更多信息:stackoverflow.com/a/20689837/3784008。简短说明:在您的分叉进程完成代码运行后调用exit,否则新生成的ruby 进程将继续在后台运行。
    • exit 这种形式的 fork 不需要使用默认代码,因为“块在子进程中运行,并且子进程以零状态终止。”为避免创建僵尸,您需要在父进程中使用Process.waitProcess.detachruby-doc.org/core-2.2.3/Kernel.html#method-i-fork
    【解决方案3】:

    在 1.9 中,您可以使用 Process.spawn 命令。 另见http://en.wikibooks.org/wiki/Ruby_Programming/Running_Multiple_Processes

    【讨论】:

      【解决方案4】:

      如果您乐于使用线程而不是进程,那么像这样的东西可能更适合多叉:

      def doit(x)
          sleep(rand(10))
          puts "Done... #{x}"
      end
      
      thingstodo = ["a","b","c","d","e","f","g"]
      tasklist = []
      
      # Set the threads going
      
      thingstodo.each { |thing|
          task = Thread.new(thing) { |this| doit(this) } 
          tasklist << task
      } 
      
      # Wait for the threads to finish
      
      tasklist.each { |task|
          task.join
      }
      

      请参阅下面 John Topley 的优秀 cmets 和参考资料,了解 Ruby 执行模型及其限制。


      刚刚编辑以纠正一个明显的错误(未分配任务),并遵循@(Jason King) 的建议。

      【讨论】:

      • 大概这些是绿色线程而不是正确的操作系统线程?
      • 阅读这篇关于 Ruby 1.9 的文章:igvita.com/2008/11/13/concurrency-is-a-myth-in-ruby
      • 应该是:Thread.new(thing) { |it| doit(it) } 因为thing在每次迭代时都会被重置,所以不能保证正确的线程会得到正确的thing
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-05
      • 2011-01-31
      • 2012-06-09
      • 1970-01-01
      • 2023-03-10
      • 1970-01-01
      • 2012-05-10
      相关资源
      最近更新 更多