Ruby 从分叉进程返回数据
如果我这样做Ruby 从分叉进程返回数据,ruby,process,fork,Ruby,Process,Fork,如果我这样做 Process.fork do x end 我如何知道x返回了什么(例如true/fase/string) (写入文件/数据库不是选项…根据文档: 如果指定了块,则该块将在子流程中运行,子流程将以零状态终止 因此,如果用块调用它,它将返回0。否则,它的功能基本上与Unix上的fork()系统调用相同(父进程接收新进程的PID,子进程接收nil)。两个Unix进程之间的fork通信主要是返回码,仅此而已。但是,您可以在两个进程之间打开一个filedescriptor,并通
Process.fork do
x
end
我如何知道x返回了什么(例如true/fase/string)
(写入文件/数据库不是选项…根据文档: 如果指定了块,则该块将在子流程中运行,子流程将以零状态终止
因此,如果用块调用它,它将返回0。否则,它的功能基本上与Unix上的
fork()
系统调用相同(父进程接收新进程的PID,子进程接收nil
)。两个Unix进程之间的fork通信主要是返回码,仅此而已。但是,您可以在两个进程之间打开一个filedescriptor,并通过该filedescriptor在进程之间传递数据:这是正常的Unix管道方式
如果要传递Marshal.dump()和Marshal.load()值,则可以轻松地在这些Ruby进程之间传递Ruby对象。如果子进程只需要一小段Ruby代码,则可以使用共享内存来传递。类似于以下的方法将起作用:
str = 'from parent'
Thread.new do
str = 'from child'
end
sleep(1)
puts str # outputs "from child"
然而,并发性可能非常棘手,并且以这种方式访问共享内存是一个很大的原因——任何时候,当你有一个变量,而另一个进程可能会从你下面改变它时,你都应该非常小心。或者,您可以使用管道,它更麻烦,但对于除最琐碎的代码之外的任何代码都可能更安全,还可以用于运行任何任意命令。下面是一个例子,直接来自IO.popen的rdoc:
f = IO.popen("uname")
p f.readlines # outputs "Darwin", at least on my box :-)
事实上,我们只是需要在一个小时内处理这个问题。我发了一些关于它的帖子 基本上,您要做的是在父级和子级中打开一个管道,并让子级写入管道。下面是一种在子进程中运行块内容并返回结果的简单方法:
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
请注意,如果在子对象中执行require,则无法访问父对象中的该库,因此无法使用此方法返回该类型的对象。但是,您可以返回在这两种语言中都可用的任何类型
还要注意,这里的很多细节(read.close
,Process.wait2(pid)
)都是内务处理细节,所以如果您经常使用这些细节,您可能应该将其移到可以重用的实用程序库中
最后,请注意,这在Windows或JRuby上不起作用,因为它们不支持分叉。感谢所有的答案,我已经启动并运行了我的解决方案,仍然需要了解如何处理非分叉环境,但现在它可以工作:)
您可以在操作中看到它@我将在过程中发现的所有解决方案(一些其他问题,如用户退出+管道缓冲区)都打包到了。现在,它非常简单:
results = Parallel.map([1,2,3],:in_processes=>4) do |i|
execute_something(i)
end
或
是的,您可以创建一个子流程来执行内部的块 我建议: 当然,它可以防止副作用:
arr = ['foo']
Aw.fork! { arr << 'FUU' } # => ["foo", "FUU"]
arr # => ["foo"]
arr=['foo']
啊,福克!{arr[“foo”,“FUU”]
arr#=>[“foo”]
这有助于获取“x”返回的内容吗?子进程在单独的进程中运行(显然),因此要获取任何“x”的值是的,您可能必须通过套接字、管道或类似的方式进行通信。我怀疑您是否可以,例如,在块内设置反映在块外的变量,因为子进程有单独的内存,等等。您看到我在回答中提供的隔离测试链接了吗?它处理分叉和非分叉环境,以及可能已经完成了您需要的所有操作。您可以在这里传递对象,甚至类作为参数吗?我真的可以使用一种方法来分叉一个进程,并将整个环境传递给它。
results = Parallel.map([1,2,3],:in_threads=>4) do |i|
execute_something(i)
end
Aw.fork! { 6 * 7 } # => 42
arr = ['foo']
Aw.fork! { arr << 'FUU' } # => ["foo", "FUU"]
arr # => ["foo"]