Práctica: Uso de IPC::Run3

Reescriba la práctica Ejecución Controlada de Un Programa 1.9 usando IPC::Run3.

Casiano Rodríguez León
2010-03-22
RDER="0" ALT="previous" SRC="prev.png"> contents index PP2PP2 moodlepsmodulosperlmonksperldocgoogleetsiiullpcgull
Sig: Práctica: Uso de IPC::Run3 Sup: Ejecucion de Programas Ant: Repaso
Casiano Rodríguez León
2010-04-19
gopcgull.gif" ALT="pcgull">
Sig: Práctica: Calculo Usando Pipes Sup: Pipes con nombre Ant: Pipes con nombre
Casiano Rodríguez León
2010-04-20
/H4>

El siguiente código muestra como usar pipes con nombre para comunicar con una aplicación externa: la calculadora bc.

pp2@europa:~/src/perl/pipesconnombre$ cat -n bidirwithnamedpipes.pl
  1  #!/usr/bin/perl -w
  2  use strict;
  3  use POSIX qw{EWOULDBLOCK mkfifo};
  4  use File::Temp qw/ tempfile tempdir /;
  5  use IO::Prompt;
  6  use File::Spec;
  7  use Time::HiRes qw{usleep};
  8
  9  my $tmp = File::Spec->tmpdir();
 10  my $dir = tempdir( "$tmp/PIPEEXAMPLEXXXX", CLEANUP => 1 );
 11  my $out = "$dir/me2bc";
 12  my $in = "$dir/bc2me";
 13
 14  mkfifo $out, 0755;
 15  mkfifo $in, 0755;
 16
 17  $SIG{PIPE} = sub {
 18    warn "received SIGPIPE. Exiting!\n";
 19    exit(1);
 20  };
 21
 22  prompt "Run \n\tbc < $out &> $in\n".
 23         "in another terminal, then press enter: ";
 24
 25  open (my $fout, "> $out");
 26  open (my $fin, "$in");
 27  $fin->blocking(0);
 28
 29  my $result;
 30  while (prompt("Expression (CTRL-D to end): ", '-l')) {
 31    
 32    print "Sending expression to external 'bc' process ...\n";
 33    syswrite $fout, $_;
 34    usleep(10);
 35    my $bytes = sysread $fin, $result, 1024;
 36    if (defined($bytes))  {
 37      if ($bytes) {
 38        print "Obtained result from external 'bc' process:\n\t$result";
 39      }
 40      else { # EOF
 41        warn "bc process broken!\n";
 42        last;
 43      }
 44    }
 45    else {
 46      print "Nothing has arrived (yet) ...\n";
 47    }
 48  }

La función sysread cuando se usa sobre un manejador sin bloqueo devuelve undef si no hay nada disponible. En tal caso la variable $! contiene el código de error EWOULDBLOCK (definida en POSIX). Esta situación no debe confundirse con la devolución de un cero, la cual indica la presencia del final de fichero.

El manejo de escrituras sin bloqueo es similar. El retorno de un valor undef señala la imposibilidad de escribir. Si la escritura sólo se ha podido hacer parcialmente es responsabilidad del programador intentarlo posteriormente.

Ahora ejecutamos el programa en una terminal:

pp2@europa:~/src/perl/pipesconnombre$ ./bidirwithnamedpipes.pl
Run
        bc < /tmp/PIPEEXAMPLEgVQX/me2bc &> /tmp/PIPEEXAMPLEgVQX/bc2me
in another terminal, then press enter:

Sigamos las instrucciones: copiamos la línea en otra terminal:

pp2@europa:~$  bc < /tmp/PIPEEXAMPLEgVQX/me2bc &> /tmp/PIPEEXAMPLEgVQX/bc2me
El proceso se queda en espera. Obśervese que hemos redirigido tanto la salida estandar (stdout) como la salida de errores (stderr) al pipe con nombre /tmp/PIPEEXAMPLEgVQX/bc2me (Véase por ejemplo BASH Programming - Introduction HOW-TO).

Ahora continuamos en la otra terminal introduciendo expresiones:

Expression (CTRL-D to end): 2*3
Sending expression to external 'bc' process ...
Obtained result from external 'bc' process:
        6
Expression (CTRL-D to end): 4+5
Sending expression to external 'bc' process ...
Obtained result from external 'bc' process:
        9
Expression (CTRL-D to end): a=2
Sending expression to external 'bc' process ...
Nothing has arrived (yet) ...
Expression (CTRL-D to end): a
Sending expression to external 'bc' process ...
Obtained result from external 'bc' process:
        2
Ahora pulsamos CTRL-C en la terminal en la que esta ejecutándose bc. El proceso correspondiente a ./bidirwithnamedpipes.pl detecta la señal de SIGPIPE una vez leída la entrada:
Expression (CTRL-D to end):
Sending expression to external 'bc' process ...
received SIGPIPE. Exiting!

pp2@europa:~/src/perl/pipesconnombre$

Ejercicios

  1. ¿Que hace la línea use POSIX qw{EWOULDBLOCK mkfifo}?
  2. ¿Que hace la línea use File::Temp qw/ tempfile tempdir /;
  3. ¿Que funciones provee IO::Prompt?
  4. ¿Para que sirve File::Spec?
  5. ¿Para que srive Time::HiRes?
  6. ¿Que contiene el hash %SIG?
  7. ¿En que módulo esta el método blocking?
  8. ¿Que devuelve sysread si no se leyó nada?
  9. ¿Que devuelve sysread si se leyó el final de fichero?
  10. Describa situaciones en las que podría ser ventajoso utilizar pipes con nombre



Subsecciones
Casiano Rodríguez León
2010-05-05