Frage

Wenn ich das tue

Process.fork do 
  x 
end 

Wie kann ich wissen, was zurückgegeben x (z true / fase / string)?

(Schreiben in eine Datei / Datenbank ist keine Option ...)

War es hilfreich?

Lösung 3

Ich wickelte alle Lösungen, die ich auf dem Weg zu finden (einige andere Probleme wie Benutzer + Rohr-Puffer verlass) in Rubin parallel gem . Nun ist es so einfach wie:

results = Parallel.map([1,2,3],:in_processes=>4) do |i|
  execute_something(i)
end

oder

results = Parallel.map([1,2,3],:in_threads=>4) do |i|
  execute_something(i)
end

Andere Tipps

Wir tatsächlich hatten gerade dieses Problem in behandeln Rails Isolationsprüfung . Ich stellte darüber einig auf meinem Blog .

Im Grunde, was Sie tun möchten, ist offen ein Rohr in den Eltern und Kind, und hat das Kind auf das Rohr schreiben. Hier ist eine einfache Möglichkeit, den Inhalt eines Blockes in einem untergeordneten Prozess und wieder um das Ergebnis zu laufen:

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

Dann könnten Sie laufen:

do_in_child do
  require "some_polluting_library"
  SomePollutingLibrary.some_operation
end

Beachten Sie, wenn Sie ein in dem Kind benötigen tun, werden Sie keinen Zugang zu dieser Bibliothek in den Eltern haben, so dass Sie nicht ein Objekt dieser Art mit dieser Methode zurückgeben können. Sie können jedoch jede Art zurück, die in beide verfügbar ist.

Beachten Sie auch, dass viele der Details hier (read.close, Process.wait2(pid)) sind meist Housekeeping Details, wenn Sie also viel diese verwenden, sollten Sie wahrscheinlich diese in eine Utility-Bibliothek bewegen, die Sie wiederverwenden können.

Schließlich ist zu beachten, dass dies nicht auf Windows oder JRuby funktionieren wird, da sie nicht Forking unterstützen.

Danke für alle Antworten, habe ich meine Lösung und läuft, müssen noch sehen, wie nicht-Forking Umgebungen zu handhaben, aber jetzt funktioniert es:)

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

Sie können es in Aktion sehen @ parallel_specs Rails Plugin

Ja, können Sie einen Subprozess erstellen einen Block innerhalb auszuführen.

Ich empfehle der aw gem :

Aw.fork! { 6 * 7 } # => 42

Natürlich ist es verhindert, dass Nebenwirkungen:

arr = ['foo']
Aw.fork! { arr << 'FUU' } # => ["foo", "FUU"]
arr # => ["foo"]

Nach der Dokumentation:

  

Wenn ein Block angegeben wird, dass der Block in der subprocess ausgeführt wird, und die Subprozess endet mit einem Status von Null.

Also, wenn Sie es mit einem Block aufrufen, gibt es 0. Ansonsten funktioniert es im Grunde das gleiche wie das fork() Systemaufruf auf Unix (das Mutter empfängt die PID des neuen Prozesses, das Kind nil erhält).

Die Gabel Kommunikation zwischen zwei Unix-Prozessen ist in erster Linie der Return-Code und nichts mehr. Allerdings Sie eine FileDescriptor zwischen den beiden Prozessen öffnen konnten und die Datenübertragung zwischen den Prozessen über diesen FileDescriptor. Dies ist die normale Unix Rohr Art und Weise

Wenn Sie Marshal.dump () und Marshal.load () Werte übergeben würden, könnte man leicht Ruby-Objekte zwischen diesen Ruby-Prozessen übergeben.

Sie können die Shared-Memory, dies zu tun, wenn das Kind nur ein kleines Stück von Ruby-Code sein muss. So etwas wie die folgenden funktionieren:

str = 'from parent'

Thread.new do
  str = 'from child'
end

sleep(1)

puts str    # outputs "from child"

Concurrency kann ziemlich schwierig sein, aber, und auf diese Weise Shared-Memory-Zugriff ist ein großer Teil des Grundes - jedes Mal, wenn Sie eine Variable haben und ein anderen Prozess könnte es unter Ihnen ändern, sollten Sie sehr vorsichtig sein. Alternativ können Sie auch ein Rohr verwendet werden, die mehr umständlich ist aber wahrscheinlich sicherer für alle, aber die meist trivialen Codes, und können auch verwendet werden, jeden beliebigen Befehl auszuführen. Hier ist ein Beispiel, gerade aus dem rdoc für IO.popen:

f = IO.popen("uname")
p f.readlines     # outputs "Darwin", at least on my box  :-)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top