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
