从派生进程
回答
我将沿途发现的所有解决方案(如用户退出+管道缓冲区等一些其他问题)包装为ruby parallel gem。现在,它是那么容易,因为:
results = Parallel.map([1,2,3],:in_processes=>4) do |i|
execute_something(i)
end
或
results = Parallel.map([1,2,3],:in_threads=>4) do |i|
execute_something(i)
end
根据文档:
如果指定了一个块,该块是在子进程运行,并且子进程终止状态为零。
所以,如果你有一个块中调用它,则返回0。否则,它的功能基本相同,在Unix上fork()
系统调用(父接收新进程的PID,孩子接受nil
)。
两个Unix进程之间的fork通信主要是返回码,仅此而已。但是,您可以在两个进程之间打开一个文件描述符,并通过此文件描述符在进程之间传递数据:这是普通的Unix管道方式。
如果您要传递Marshal.dump()和Marshal.load()值,那么您可以轻松地在这些Ruby进程之间传递Ruby对象。
如果孩子只需要一小段代码就可以使用共享内存来做到这一点。像下面的内容将工作:
str = 'from parent'
Thread.new do
str = 'from child'
end
sleep(1)
puts str # outputs "from child"
并发性可能会非常棘手,虽然和访问共享内存这种方式的很大一部分原因 - 你已经有了一个变量,另一个进程可能会改变它的任何时间从你的下面出来,你应该非常谨慎。或者,您可以使用管道,这种管道比较笨重,但对于最简单的代码可能更安全,也可以用来运行任意命令。下面是一个例子,直出的RDoc为IO.popen的:
f = IO.popen("uname")
p f.readlines # outputs "Darwin", at least on my box :-)
实际上,我们刚刚在Rails isolation testing来处理这个问题。我发布了一些关于它的一些on my blog。
基本上,你想要做的是在父母和孩子中打开一个管道,并让孩子写入管道。这里有一个简单的方法来运行一个块的内容在一个子进程,并取回结果:
def do_in_child
read, write = IO.pipe
pid = fork do
read.close
result = yield
Marshal.dump(result, write)
exit!(0) # skips exit handlers.
end
write.close
result = read.read
Process.wait(pid)
raise "child failed" if result.empty?
Marshal.load(result)
end
然后,你可以运行:
do_in_child do
require "some_polluting_library"
SomePollutingLibrary.some_operation
end
请注意,如果你做一个在孩子需要,您将无法访问父库中的该库,因此无法使用此方法返回该类型的对象。但是,您可以返回任何可用的类型。
还要注意很多的细节在这里(read.close
,Process.wait2(pid)
)大都是看家的细节,所以如果你使用这个有很多你应该移到了这一点,到公共图书馆,你可以重复使用。
最后,请注意,这不适用于Windows或JRuby,因为它们不支持分叉。
感谢所有的答案,我得到了我的解决方案和运行,还需要了解如何处理非分叉的环境,但现在它的工作原理:)
read, write = IO.pipe
Process.fork do
write.puts "test"
end
Process.fork do
write.puts 'test 2'
end
Process.wait
Process.wait
write.close
puts read.read
read.close
,你可以看到它在行动@parallel_specs Rails plugin
你见过我在答案中提供的隔离测试链接吗?它可以处理分叉和非分叉环境,并且可能已经做好了你需要的一切。 – 2009-07-02 21:21:36
是的,你可以创建一个子进程来执行内部块。
我建议the aw
gem:
Aw.fork! { 6 * 7 } # => 42
当然,它可以防止副作用:
arr = ['foo']
Aw.fork! { arr << 'FUU' } # => ["foo", "FUU"]
arr # => ["foo"]
- 1. 顺序派生进程
- 2. STD在派生进程
- 3. 如何从一个子进程派生子进程分别
- 4. 从父进程派生/产生许多node.js进程的最高性能方式
- 5. Python的派生进程不会死
- 6. WildFly不能派生新进程连接
- 7. 有问题与派生进程
- 8. 从QAbstractScrollArea派生
- 9. 继承,从派生类派生
- 10. 如何从Numpy的polyfit派生方程?
- 11. 节点webkit - 无法派生子进程(错误:产生EACCES)
- 12. 设计我的程序,以避免必须从基础派生到派生类
- 13. EXECL只在派生进程中执行一次,C编程
- 14. 强制调用从派生
- 15. iPhone tableview:titleForHeaderInSection从数组派生
- 16. 从基类INITIALISE派生类
- 17. Casating从派生基地,ambiguouty
- 18. 从unboound派生行DataGridVew
- 19. 派生UDID从iPhone序列#
- 20. 从泛型T派生类
- 21. 从泛型类派生
- 22. 从模板类派生?
- 23. 派生类C++ BankAccount程序
- 24. 派生类的Ruby线程?
- 25. 从派生自同一类的类派生的C++子类
- 26. 获取派生进程的标准输出/标准错误在子进程
- 27. 如何显示从二进制文字派生的位图板?
- 28. 派生二进制树从后序列表或预订列表
- 29. 如何从Propel的派生表中进行选择?
- 30. 实现对从流派生的类进行处理
这怎么能帮助得到什么的 'X' 回来了? – grosser 2009-07-02 19:43:40
子进程运行在一个单独的进程中(很明显),因此要获取任何“x”的值,您可能必须通过套接字,管道或类似的东西进行通信。我怀疑你可以,例如在块内部设置变量,因为子进程具有单独的内存等。 – mipadi 2009-07-02 19:51:29