【发布时间】:2008-11-20 22:19:37
【问题描述】:
我想将我的主进程中的一段代码卸载到子进程以使其同时运行。我还想拥有生成的子进程的 PID,以便在必要时监视并杀死它。
【问题讨论】:
标签: ruby
我想将我的主进程中的一段代码卸载到子进程以使其同时运行。我还想拥有生成的子进程的 PID,以便在必要时监视并杀死它。
【问题讨论】:
标签: ruby
除了 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 等待 any 子进程,因此在更一般的情况下,即使该特定子进程,此代码 sn-p 也会退出父进程以上不退出。更准确的版本会改为 Process.wait(pid)。
fork,因为那只在Unix上)?
Process.waitall。父母将等到 ALL 孩子退出。
您可以使用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。
【讨论】:
exit 有点困惑——为什么(或何时)需要它?
exit 是确保分叉进程终止所必需的。否则,您最终可能会遇到僵尸或孤儿进程。更多信息:stackoverflow.com/a/20689837/3784008。简短说明:在您的分叉进程完成代码运行后调用exit,否则新生成的ruby 进程将继续在后台运行。
exit 这种形式的 fork 不需要使用默认代码,因为“块在子进程中运行,并且子进程以零状态终止。”为避免创建僵尸,您需要在父进程中使用Process.wait 或Process.detach。 ruby-doc.org/core-2.2.3/Kernel.html#method-i-fork
在 1.9 中,您可以使用 Process.spawn 命令。 另见http://en.wikibooks.org/wiki/Ruby_Programming/Running_Multiple_Processes
【讨论】:
如果您乐于使用线程而不是进程,那么像这样的东西可能更适合多叉:
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) 的建议。
【讨论】:
Thread.new(thing) { |it| doit(it) } 因为thing在每次迭代时都会被重置,所以不能保证正确的线程会得到正确的thing