2009-10-22 18 views
10

Ryan Tomayko ha provocato una tempesta di fuoco con this post sull'utilizzo dei comandi di controllo processo Unix.Utilizzo dei metodi di controllo processo Unix in Ruby

Dovremmo fare di più. Molto più di questo. Sto parlando di fork (2), execve (2), pipe (2), socketpair (2), select (2), kill (2), sigaction (2), e così via e così via. Questi sono i nostri amici. Vogliono così tanto solo per aiutarci.

Ho un po 'di codice (un clone delayed_job per DataMapper che penso che si adatterebbe a destra con questo, ma io non sono chiare su come sfruttare i comandi elencati. Tutte le idee su come migliorare questo codice?

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 

risposta

3

Ahh sì ... i pericoli di "dovremmo fare di più di questo" senza spiegare ciò che ciascuno di coloro che fanno e in quali circostanze si sarebbe li usano. Per una cosa del genere delayed_job si può anche stare usando fork senza sapere che stai usando fork. Detto questo, non importa. Ryan stava parlando di usare fork per i server di preforking. delayed_job utilizza fork per trasformare un processo in un demone. Stessa chiamata di sistema, scopi diversi. L'esecuzione di delayed_job in primo piano (senza fork) in background (con fork) comporterà una differenza di prestazioni trascurabile.

Tuttavia, se si scrive un server che accetta connessioni simultanee, ora il consiglio di Ryan è giusto in the money.

  • fork: crea una copia del processo originale
  • execve: smette di eseguire il file corrente e inizia l'esecuzione di un nuovo file nello stesso processo (molto utile in compiti rake)
  • pipe: crea un tubo (due descrittori di file, uno per la lettura, uno per la scrittura)
  • socketpair: come un tubo, ma per le prese
  • select: vi aspettiamo per uno o più dei descrittori di file multipli da leggere y con un timeout
  • kill: utilizzato per inviare un segnale a un processo
  • sigaction: permette di cambiare ciò che accade quando un processo riceve un segnale
+0

Quindi invece di creare un thread (verde), potrei usare fork (2) invece di restituire un PID. Questo molto ho fatto. Come lavoro con il blocco per trap ('USR1') che risveglia il thread quando il nuovo lavoro raggiunge la coda? Come potrei creare più di un processo e convincerli a tirare fuori la coda in modo ottimale. La magia sembra essere in pipe e selezionare ma non capisco le complessità. Posso usare il demone gem per creare un processo demone che usa la forchetta sotto il cofano. Voglio avviare alcuni processi figlio per eseguire la coda. –

+0

Dipende da cosa "lavoro" significa in questo contesto. Se "lavoro" è I/O, potrebbe essere diverso e sì, 'select' è importante. Preferisco progettare code di lavoro in modo tale che il lavoro possa essere eseguito in qualsiasi ordine. Quindi, se l'unità di lavoro n. 1 viene eseguita contemporaneamente all'unità di lavoro n. 2, non è un problema. Per quanto riguarda la gemma dei daemon ... l'ho usata, ma ora uso direttamente 'fork' o uso la mia libreria ChainGang.Ho scoperto che i daemon nascondevano troppe cose importanti, e non era necessario un sovraccarico per qualcosa che in realtà non è così difficile. Si noti che ChainGang è di qualità molto alpha. –

+0

In sostanza, preoccuparsi di "estrapolare la coda in modo ottimale" non ha molto senso in molti contesti. O stai lavorando con I/O, nel qual caso probabilmente non stai usando una coda 'delayed_job', o stai eseguendo le cose come unità di lavoro separate, nel qual caso' select' e 'pipe' non ne fanno senso. Ad ogni modo, il modo giusto per gestire una coda di lavoro è quello di afferrare tutto ciò che è in cima ogni volta che sei libero. E se non c'è niente lì, probabilmente è OK bloccare solo fino a quando non c'è. –

Problemi correlati