El siguiente ejemplo activa un conjunto de procesos y procede posteriormente (líneas 49-50) a su eliminación usando la señal HUP .
La señal HUP
a diferencia de la señal
KILL puede ser ignorada. Si un proceso
establece
local $SIG{HUP} = 'IGNORE'
ignorará la señal.
La señal HUP
suele ser recibida por un programa
que fué ejecutado por el usuario
desde la línea de comandos cuando este cierra la ventana
o sale del intérprete (bash
, csh
, etc.).
En Unix un buen número de demonios siguen
el convenio de usar la señal HUP
para reinicializar (reset
) el servidor.
Por ejemplo, un servidor cuya conducta depende de un fichero de
configuración suele responder a la señal HUP
volviendo a leer y analizar el fichero. Se produce así
la consiguiente reconfiguración del servidor.
lhp@nereida:~/Lperl/src/perl_networking/ch2$ cat -n killchildren.pl 1 #!/usr/bin/perl -w 2 use strict; 3 use List::MoreUtils qw(part); 4 use Proc::ProcessTable; 5 $| = 1; 6 7 sub create_child { 8 my ($id, $task) = splice @_, 0, 2; 9 my $pid; 10 11 return $pid if $pid = fork(); 12 die "Cannot fork $!" unless defined $pid; 13 $task->($id, @_); # do something 14 exit; 15 } 16 17 sub parfor { 18 my $LAST = shift; 19 my $task = shift; 20 my @pid; 21 22 $pid[0] = $$; 23 $pid[$_] = create_child($_, $task, @_) for 1..$LAST; 24 return @pid; 25 } 26 27 sub task { 28 my $id = shift; 29 30 print "Hello, from process $id. Args: @_\n"; 31 sleep(10); 32 } 33 34 sub print_alives { 35 my @pids = @_; 36 37 my ($dead, $alive) = part { kill 0, $_ } @pids; 38 39 print "$_ is alive\n" for @$alive; 40 } 41 42 sub ps { 43 my $FORMAT = "%-6s %-11s %-8s %-24s %s\n"; 44 printf($FORMAT, "PID", "TTY", "STAT", "START", "COMMAND"); 45 foreach my $p ( @_ ){ 46 printf($FORMAT, 47 $p->pid, 48 $p->ttydev, 49 $p->state, 50 scalar(localtime($p->start)), 51 $p->cmndline); 52 } 53 } 54 55 #main 56 my $np = shift || 4; 57 58 my @pids = &parfor($np, \&task, 1..3); 59 60 my $group = getpgrp($$); 61 print "Group: $group\n"; 62 63 print_alives(@pids); 64 65 my $p = Proc::ProcessTable->new(); 66 my @children = grep { $_->pgrp == $group } @{$p->table}; 67 ps(@children); 68 69 local $SIG{HUP} = 'IGNORE'; 70 kill HUP => -$group; 71 sleep(1); 72 73 @children = grep { $_->pgrp == $group } @{$p->table}; 74 ps(@children); 75 76 my $fully_dead = wait(); 77 78 print_alives(@pids); 79 print "The only synchronized process is: $fully_dead\n";
La función getpgrp (línea 43) retorna el grupo de proceso cuyo PID se le pasa como argumento.
Al ejecutarlo tenemos la salida:
lhp@nereida:~/Lperl/src/perl_networking/ch2$ killchildren.pl Hello, from process 1. Args: 1 2 3 Hello, from process 2. Args: 1 2 3 Hello, from process 3. Args: 1 2 3 Hello, from process 4. Args: 1 2 3 Group: 17585 17585 is alive 17586 is alive 17587 is alive 17588 is alive 17589 is alive PID TTY STAT START COMMAND 17585 /dev/pts/17 run Mon Mar 31 12:16:46 2008 /usr/bin/perl -w ./killchildren.pl 17586 /dev/pts/17 sleep Mon Mar 31 12:16:46 2008 /usr/bin/perl -w ./killchildren.pl 17587 /dev/pts/17 sleep Mon Mar 31 12:16:46 2008 /usr/bin/perl -w ./killchildren.pl 17588 /dev/pts/17 sleep Mon Mar 31 12:16:46 2008 /usr/bin/perl -w ./killchildren.pl 17589 /dev/pts/17 sleep Mon Mar 31 12:16:46 2008 /usr/bin/perl -w ./killchildren.pl PID TTY STAT START COMMAND 17585 /dev/pts/17 run Mon Mar 31 12:16:46 2008 /usr/bin/perl -w ./killchildren.pl 17586 /dev/pts/17 defunct Mon Mar 31 12:16:46 2008 killchildren.pl 17587 /dev/pts/17 defunct Mon Mar 31 12:16:46 2008 killchildren.pl 17588 /dev/pts/17 defunct Mon Mar 31 12:16:46 2008 killchildren.pl 17589 /dev/pts/17 defunct Mon Mar 31 12:16:46 2008 killchildren.pl 17585 is alive 17587 is alive 17588 is alive 17589 is alive The only synchronized process is: 17586 lhp@nereida:~/Lperl/src/perl_networking/ch2$Observe como los procesos 17587-17589 quedan zombies mientras que el proceso 17586 muere al haberse sincronizado con el proceso padre (línea
my $fully_dead = wait()
).
Casiano Rodríguez León