2009-10-22 13 views
10

Ryan Tomayko löste einen ziemlichen Feuersturm mit this post über die Verwendung von Unix-Prozesssteuerbefehlen aus.Verwenden von Unix-Prozesssteuerungsmethoden in Ruby

Wir sollten mehr davon tun. Viel mehr davon. Ich spreche von fork (2), execve (2), pipe (2), socketpair (2), wählen Sie (2), kill (2), sigaction (2) und so weiter und so weiter. Das sind unsere Freunde. Sie wollen so sehr, nur um uns zu helfen.

Ich habe ein Stück Code (einen delayed_job Klon für DataMapper dass ich denke, würde direkt mit diesem passen, aber ich bin mir nicht klar, wie man die Vorteile der genannten Befehle nehmen. Alle Ideen, wie zur Verbesserung der dieser Code?

def start 
    say "*** Starting job worker #{@name}" 
    t = Thread.new do 
    loop do 
     delay = Update.work_off(self) 
     break if $exit 
     sleep delay 
     break if $exit 
    end 
    clear_locks 
    end 

    trap('TERM') { terminate_with t } 
    trap('INT') { terminate_with t } 

    trap('USR1') do 
    say "Wakeup Signal Caught" 
    t.run 
    end 
end 

Antwort

3

Ahh ja ... die Gefahren von „Wir sollten mehr davon tun“, ohne zu erklären, was jeder von denen sie und unter welchen Umständen Sie sie verwenden würde. Für so etwas wie delayed_job Sie können sogar Verwenden Sie fork ohne zu wissen, dass Sie fork verwenden. Das sagte, es ist wirklich egal, Ryan sprach über die Verwendung fork zum Vorbereiten von Servern. delayed_job würde fork verwenden, um einen Prozess in einen Daemon umzuwandeln. Gleicher Systemaufruf, verschiedene Zwecke. Das Ausführen von delayed_job im Vordergrund (ohne fork) vs im Hintergrund (mit fork) führt zu einem vernachlässigbaren Leistungsunterschied.

Wenn Sie jedoch einen Server schreiben, der gleichzeitige Verbindungen akzeptiert, ist Ryans Rat jetzt richtig.

  • fork: erstellt eine Kopie des ursprünglichen Prozesses
  • execve: Stoppen die aktuelle Datei und beginnt die Ausführung eine neue Datei im selben Prozess (sehr nützlich in Rake Aufgaben)
  • pipe Ausführung: erstellt ein Rohr (zwei Dateideskriptoren, ein für Lese-, ein für Schreib)
  • socketpair: wie ein Rohr, aber für Steckdosen
  • select: die können Sie für einen oder mehr von mehreren Filedeskriptoren warten zu lesenden y mit einem Timeout
  • kill: verwendet, um ein Signal an einen Prozess
  • sigaction zu senden: Damit können Sie ändern, was passiert, wenn ein Prozess ein Signal später
+0

Also anstatt einen (grünen) Thread zu erstellen, könnte ich stattdessen fork (2) verwenden und eine PID zurückgeben. So viel habe ich getan. Wie arbeite ich mit dem Block für Trap ('USR1'), der den Thread aufweckt, wenn ich einen neuen Job in die Warteschlange stoße? Wie würde ich mehr als einen Prozess erstellen und sie dazu bringen, die Warteschlange optimal abzuwickeln? Die Magie scheint in der Leitung zu sein und zu wählen, aber ich verstehe die Feinheiten nicht. Ich kann den Daemon-Edelstein verwenden, um einen Daemon-Prozess zu erstellen, der Gabel unter der Haube verwendet. Ich möchte einige untergeordnete Prozesse starten, um die Warteschlange auszuführen. –

+0

Hängt davon ab, was "Arbeit" in diesem Zusammenhang bedeutet. Wenn "work" I/O ist, könnte es anders sein und yeah, 'select' ist wichtig. Ich bevorzuge es, Arbeitswarteschlangen so zu gestalten, dass Arbeiten in beliebiger Reihenfolge ausgeführt werden können. Wenn Arbeitseinheit 1 also gleichzeitig mit Arbeitseinheit 2 ausgeführt wird, ist das kein Problem. Was die Daemons betrifft, habe ich sie benutzt, aber jetzt benutze ich 'fork' direkt oder benutze meine ChainGang-Bibliothek.Ich fand, dass Dämonen zu viel wichtiges Zeug verbargen, und es war unnötiger Overhead für etwas, das eigentlich gar nicht so schwer ist. Beachten Sie, dass ChainGang sehr Alpha-Qualität ist. –

+0

Im Grunde macht es in den meisten Kontexten keinen Sinn, sich Sorgen zu machen, ob man die Warteschlange optimal abwickeln soll. Entweder arbeiten Sie mit I/O, in diesem Fall verwenden Sie wahrscheinlich keine "delayed_job" -Warteschlange, oder Sie führen Dinge als diskrete Arbeitseinheiten aus. In diesem Fall machen 'select' und' pipe' keine Sinn. Wie auch immer, der richtige Weg, um mit einer Arbeitswarteschlange fertig zu werden, besteht darin, einfach alles, was oben ist, zu greifen, wann immer Sie frei sind. Und wenn da nichts ist, ist es wahrscheinlich in Ordnung, einfach zu blocken, bis es da ist. –