從派生進程
回答
我將沿途發現的所有解決方案(如用戶退出+管道緩衝區等一些其他問題)包裝爲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. 順序派生進程
- 3. STD在派生進程
- 4. 如何從一個子進程派生子進程分別
- 5. 從父進程派生/產生許多node.js進程的最高性能方式
- 6. 共享指針多個派生進程
- 7. 有問題與派生進程
- 8. 紅寶石 - 對派生進程
- 9. WildFly不能派生新進程連接
- 10. Python的派生進程不會死
- 11. 從QAbstractScrollArea派生
- 12. wpf從派生的控件派生
- 13. 繼承,從派生類派生
- 14. 從派生的類
- 15. 如何從Numpy的polyfit派生方程?
- 16. 節點webkit - 無法派生子進程(錯誤:產生EACCES)
- 17. 設計我的程序,以避免必須從基礎派生到派生類
- 18. 從UIColors中獲取RGB值從十六進制顏色派生
- 19. EXECL只在派生進程中執行一次,C編程
- 20. 從WinForm的派生類
- 21. 從模板類派生?
- 22. iPhone tableview:titleForHeaderInSection從數組派生
- 23. 派生列從預期
- 24. 從派生類到基類
- 25. 可以從System.ArgumentException派生嗎?
- 26. 從泛型T派生類
- 27. 從基類INITIALISE派生類
- 28. 強制調用從派生
- 29. 模板從模板派生
- 30. 派生從兩個CGPoint
這怎麼能幫助得到什麼的 'X' 回來了? – grosser 2009-07-02 19:43:40
子進程運行在一個單獨的進程中(很明顯),因此要獲取任何「x」的值,您可能必須通過套接字,管道或類似的東西進行通信。我懷疑你可以,例如在塊內部設置變量,因爲子進程具有單獨的內存等。 – mipadi 2009-07-02 19:51:29