[caracas-pm] Re: [l-desarrollo] Varios procesos hijos en Perl

Ernesto Hernandez-Novich emhn at telcel.net.ve
Tue Jun 15 09:49:53 CDT 2004


On Mon, 14 Jun 2004, Daniel Cubero Salas wrote:
> Pueden ayudarme a resolver un problema en Perl. Estoy
> programando un "disparador" de procesos a un servicio
> que escucha en un cierto puerto en Linux, la
> aplicación utiliza system() para ejecutar un cliente
> (a quien le pasa un parámetro) del servicio que
> quiero probar, hace un bucle de 4 forks que crean
> diferentes parámetros para diferenciar al cliente
> ejecutado.
[...]
> Al ejecutar "miprograma.pl", si arrancan los 4
> procesos  hijos. PERO EL PROBLEMA ES QUE: revisando
> con "ps aux" se observa que, por alguna razón,
> aparecen 4 instancias de miprograma.pl pero se
> suponía que ya no debía existir la ejecución de
> este programa, esto provoca que cuando terminal los 4
> primeros procesos hijos vuelve cada uno de esas
> instancias a crear 4 nuevos procesos hijos; y otra vez
> se repite el ciclo.

La documentación de Perl, en lo que refiere a system, es muy clara: si la
línea de comandos que pasas a system() tiene _argumentos_, entonces estos
son pasados a un _shell_ para que sean interpretados y es ese shell el que
en efecto ejecuta el programa. Esto quiere decir que tu programa hace un
fork() y dentro de cada uno se inicia un _shell_ (que mantiene el nombre de
miprograma.pl) simplemente para procesar los argumentos y es éste shell
el que luego hará otro fork() para correr el programa.

perldoc -f system para que aclares tu duda al respecto.

> He revisado varios ejemplos en los que usan el mismo
> esquema para arrancar procesos hijos con la excepción
> que usan EXEC() en lugar de SYSTEM(), hice la prueba
> con aquel comando pero la ejecución se queda detenida
> en el primer proceso hijo y no continua hasta que
> termine el anterior.

La manera correcta de hacer lo que quieres es efectivamente usando exec,
pero disociando los procesos hijos de la misma manera que se haría en C
(instalando manejadores de señales, cambiando el process group id, etc.)

Revisa

man perlipc
man perlfaq8
man perlfork

para más detalles. En particular debes tener cuidado en detectar la
muerte de los hijos (usando wait o manejando la señal SIGCLD).

No obstante, todos éstos métodos son "artesanales" y usualmente sólo
tienen sentido cuando deben ajustarse finamente los parámetros de
creación e interacción entre los procesos. Te recomendaría evitar ese
camino si no eres ducho en el manejo de procesos Unix, y que estudies
los módulos IPC::Open2 e IPC::Open3 (vienen con Perl 5.8) o bien
Proc::Daemon (está en CPAN) que son mucho más expeditos y encapsulan
la complejidad.

apt-get install libproc-daemon-perl

Según interpreto de tu explicación, el asunto es que tienes un programa
"polifuncional", i.e. el argumento que le estás pasando es para que
cambie su funcionamiento. Hay una manera mucho más astuta (y "estilo
Unix") de lograr eso _sin_ pasarle argumentos: digamos que el programa
se llama 'foo' y que yo le paso argumentos diferentes para que tenga las
funciones 'bar', 'baz', 'qux', etc. Entonces, tu solución es equivalente
a algo como

$ foo -bar
$ foo -baz
$ foo -qux

y lo que podrías hacer es crear enlaces a foo con los otros nombres

$ ln foo bar
$ ln foo baz
$ ln foo qux

y que en el programa principal de foo verifique cómo ha sido llamado (te
basta con mirar $0), e.g.

#!/usr/bin/perl
# Colocar esto en foo, luego hacer los enlaces
sub foo { print "Soy foo\n" };
sub bar { print "Soy bar\n" };
sub baz { print "Soy baz\n" };
for ($0) {
  /foo/ and foo;
  /bar/ and bar;
  /baz/ and baz;
}
-- 
Ernesto Hernández-Novich - On Linux 2.6.6 i686 - Unix: Live free or die!
Geek by nature, Linux by choice, Debian of course.
If you can't apt-get it, it isn't useful or doesn't exist.
GPG Key Fingerprint = 438C 49A2 A8C7 E7D7 1500 C507 96D6 A3D6 2F4C 85E3



More information about the caracas-pm mailing list