Perl - Gestione dei processi

È possibile utilizzare Perl in vari modi per creare nuovi processi secondo le proprie esigenze. Questo tutorial elencherà alcuni metodi importanti e usati più di frequente per creare e gestire processi Perl.

  • Puoi usare variabili speciali $$ o $PROCESS_ID per ottenere l'ID del processo corrente.

  • Ogni processo creato utilizzando uno dei metodi menzionati, mantiene il proprio ambiente virtuale all'interno %ENV variabile.

  • Il exit() funzione esce sempre solo dal processo figlio che esegue questa funzione e il processo principale nel suo insieme non uscirà a meno che tutti i processi figlio in esecuzione non siano terminati.

  • Tutti gli handle aperti sono dup () - ed nei processi figlio, in modo che la chiusura di qualsiasi handle in un processo non influisca sugli altri.

Operatore Backstick

Questo modo più semplice di eseguire qualsiasi comando Unix è usare l'operatore backstick. Metti semplicemente il tuo comando all'interno dell'operatore backstick, che comporterà l'esecuzione del comando e restituirà il suo risultato che può essere memorizzato come segue:

#!/usr/bin/perl

@files = `ls -l`;

foreach $file (@files) {
   print $file;
}

1;

Quando il codice sopra viene eseguito, elenca tutti i file e le directory disponibili nella directory corrente -

drwxr-xr-x 3 root root 4096 Sep 14 06:46 9-14
drwxr-xr-x 4 root root 4096 Sep 13 07:54 android
-rw-r--r-- 1 root root  574 Sep 17 15:16 index.htm
drwxr-xr-x 3  544  401 4096 Jul  6 16:49 MIME-Lite-3.01
-rw-r--r-- 1 root root   71 Sep 17 15:16 test.pl
drwx------ 2 root root 4096 Sep 17 15:11 vAtrJdy

La funzione system ()

Puoi anche usare system()funzione per eseguire qualsiasi comando Unix, il cui output andrà all'output dello script perl. Per impostazione predefinita, è lo schermo, cioè STDOUT, ma puoi reindirizzarlo a qualsiasi file utilizzando l'operatore di reindirizzamento> -

#!/usr/bin/perl

system( "ls -l")

1;

Quando viene eseguito il codice sopra, elenca tutti i file e le directory disponibili nella directory corrente -

drwxr-xr-x 3 root root 4096 Sep 14 06:46 9-14
drwxr-xr-x 4 root root 4096 Sep 13 07:54 android
-rw-r--r-- 1 root root  574 Sep 17 15:16 index.htm
drwxr-xr-x 3  544  401 4096 Jul  6 16:49 MIME-Lite-3.01
-rw-r--r-- 1 root root   71 Sep 17 15:16 test.pl
drwx------ 2 root root 4096 Sep 17 15:11 vAtrJdy

Fai attenzione quando il tuo comando contiene variabili ambientali della shell come $ PATH o $ HOME. Prova a seguire tre scenari:

#!/usr/bin/perl

$PATH = "I am Perl Variable";

system('echo $PATH');  # Treats $PATH as shell variable
system("echo $PATH");  # Treats $PATH as Perl variable
system("echo \$PATH"); # Escaping $ works.

1;

Quando viene eseguito il codice precedente, produce il seguente risultato a seconda di cosa è impostato nella variabile di shell $ PATH.

/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin
I am Perl Variable
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin

La funzione fork ()

Perl fornisce un file fork()funzione che corrisponde alla chiamata di sistema Unix con lo stesso nome. Sulla maggior parte delle piattaforme Unix in cui è disponibile la chiamata di sistema fork (), fork () di Perl la chiama semplicemente. Su alcune piattaforme come Windows dove la chiamata di sistema fork () non è disponibile, Perl può essere costruito per emulare fork () a livello di interprete.

La funzione fork () viene utilizzata per clonare un processo corrente. Questa chiamata crea un nuovo processo che esegue lo stesso programma nello stesso punto. Restituisce il pid figlio al processo padre, 0 al processo figlio o undef se il fork non ha successo.

Puoi usare exec() all'interno di un processo per avviare l'eseguibile richiesto, che verrà eseguito in un'area del processo separata ed exec () attenderà il completamento prima di uscire con lo stesso stato di uscita di quel processo.

#!/usr/bin/perl

if(!defined($pid = fork())) {
   # fork returned undef, so unsuccessful
   die "Cannot fork a child: $!";
} elsif ($pid == 0) {
   print "Printed by child process\n";
   exec("date") || die "can't exec date: $!";
  
} else {
   # fork returned 0 nor undef
   # so this branch is parent
   print "Printed by parent process\n";
   $ret = waitpid($pid, 0);
   print "Completed process id: $ret\n";

}

1;

Quando viene eseguito il codice sopra, produce il seguente risultato:

Printed by parent process
Printed by child process
Tue Sep 17 15:41:08 CDT 2013
Completed process id: 17777

Il wait() e waitpid()può essere passato come ID pseudo-processo restituito da fork (). Queste chiamate attenderanno correttamente la fine dello pseudo-processo e restituiranno il suo stato. Se forzi senza mai aspettare che i tuoi figli usinowaitpid()funzione, accumulerai zombi. Sui sistemi Unix, puoi evitarlo impostando $ SIG {CHLD} su "IGNORE" come segue:

#!/usr/bin/perl

local $SIG{CHLD} = "IGNORE";
 
if(!defined($pid = fork())) {
   # fork returned undef, so unsuccessful
   die "Cannot fork a child: $!";
} elsif ($pid == 0) {
   print "Printed by child process\n";
   exec("date") || die "can't exec date: $!";
  
} else {
   # fork returned 0 nor undef
   # so this branch is parent
   print "Printed by parent process\n";
   $ret = waitpid($pid, 0);
   print "Completed process id: $ret\n";

}

1;

Quando viene eseguito il codice sopra, produce il seguente risultato:

Printed by parent process
Printed by child process
Tue Sep 17 15:44:07 CDT 2013
Completed process id: -1

La funzione kill ()

Perl kill('KILL', (Process List)) può essere usata per terminare uno pseudo-processo passandogli l'ID restituito da fork ().

Notare che l'utilizzo di kill ('KILL', (Process List)) su uno pseudo-processo () può in genere causare perdite di memoria, perché il thread che implementa lo pseudo-processo non ha la possibilità di ripulire le sue risorse.

Puoi usare kill() funzione per inviare qualsiasi altro segnale ai processi di destinazione, ad esempio il seguente invierà SIGINT a un processo ID 104 e 102 -

#!/usr/bin/perl

kill('INT', 104, 102);
 
1;