2012-02-09 3 views
6

Ho scoperto di recente il biforcimento di Perl e sono abbastanza innamorato. Ma una cosa mi preoccupa: se sto solo dividendo i processi da sinistra a destra, sicuramente questo causerà qualche problema da qualche parte. Esiste un ragionevole tipo di controllo che si dovrebbe usare per assicurarsi che la mia piccola applicazione non mangi tutte le risorse della mia macchina?Perl - biforcazione responsabile

prendere questo codice di esempio:

foreach my $command (@commands) { 
    my $pid = fork(); 
    if (!$defined $pid) { 
    #Fork failed. Do something. 
    } elsif ($pid == 0) { #This is the child. 
     system($command); 
     exit(0) 
    } 
} 

while (wait() != -1) {} #wait() will be -1 when the last child exits. 

Quindi questo funzionerà bene, e deporre le uova fuori un processo per gestire ogni comando. Succederà tutto in parallelo, il che è ottimo se questi comandi sono completamente indipendenti.

E se improvvisamente ho più di 5.000 comandi da eseguire? Non sarebbe saggio rinunciare a questi processi in modo sconsiderato. Quindi quale tipo di controllo dovrebbe essere implementato e come?

)

+1

Um, tenere traccia di quante hai biforcuta, e fermarsi a un max quindi non uccidi la macchina e hai presto un sysadmin arrabbiato per essere svegliato alle 3 del mattino? ;) –

+0

Ok, ma cos'è un "massimo" ragionevole? – Jeremy

+2

È sciocco chiamare 'system' dove l'hai fatto. 'system' è in pratica' fork' + 'exec' (child) +' waitpid' (parent). Cambia 'system' in' exec'. – ikegami

risposta

7

Anche se siete preoccupati per la deposizione delle uova troppi processi biforcuta, allo stesso tempo, è possibile strozzare.

O rollare il proprio (utilizzando una coda per contenere "da fork"), o meglio ancora, utilizzare il modulo Parallel::ForkManager che consente di limitare le forche simultanee tramite un parametro costruttore.

use Parallel::ForkManager; 
$pm = new Parallel::ForkManager($MAX_PROCESSES); 

prega di notare che ForkManager si prenderà cura di mietere processi figli terminati per voi tramite un "wait *" API fornite

+0

Questo suona come la strada da percorrere! Grazie. – Jeremy

3

Quando un bambino esce sta andando a rispedire un SIG_CHLD al genitore. Avrai voglia di raccoglierli come se non fosse loro saranno zombie nella tabella dei processi fino alla chiamata finale a wait alla fine del tuo script.

Chapter 16 of O'Reilly's Perl Cookbook on Google books fornisce un sacco di informazioni su questo. Fondamentalmente, devi incrementare un contatore quando stai forking i bambini, e decrementalo quando li raccogli e non forchetta quelli nuovi oltre un numero ragionevole di bambini attualmente in esecuzione.

Riguardo a cosa un "massimo ragionevole" è ... dipende dall'hardware e da cosa stanno facendo quei processi biforcati. Non c'è una risposta statica a questa domanda se non quella di testare ciò che si sta facendo e osservare l'impatto sulle prestazioni sulla macchina. Preferibilmente durante l'orario lavorativo. Dopo aver detto al sysadmin cosa stai facendo. Lui/lei potrebbe anche avere qualche consiglio.

+0

Non collegare a riproduzioni non autorizzate di materiale protetto da copyright. –

+1

Ok, collegherò alla stessa identica cosa sui libri di Google. –

1

Per assicurarsi che tu non generare più processi di quale sistema in grado di gestire in modo efficiente è possibile utilizzare i moduli come Parallel::ForkManager

0

La deposizione delle uova (forking) come molti processi come sistema in grado di supportare è chiamato fork bomb. Il sistema può bloccarsi o bloccarsi mentre la sua tabella di processo diventa satura e la memoria e la CPU sono esaurite. Sui sistemi Linux, il comando ulimit dovrebbe mostrare il numero massimo di processi utente consentiti. È possibile (dovrebbe) impostare in modo appropriato per il proprio sistema. Forking crea processi in modo esponenziale. Così, questo frammento di creare quattro processi che consumano infinita CPU fino ucciso --- una brutta, piccola bomba:

perl -e 'fork; fork; 1 while {}'