Señales a Grupos

Cuando en la llamada a kill se emplea un número negativo para identificar el proceso la señal se envía a todos los procesos con identificador de grupo igual al opuesto de ese número.

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.

Ejercicio 3.4.1   Estudie la siguiente cuestion en PerlMonks. ¿Cuales son sus sugerencias?

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
Licencia de Creative Commons
Programación Distribuida y Mejora del Rendimiento
por Casiano Rodríguez León is licensed under a Creative Commons Reconocimiento 3.0 Unported License.

Permissions beyond the scope of this license may be available at http://campusvirtual.ull.es/ocw/course/view.php?id=44.
2012-06-19