La Función fork

Cuando se llama la función fork, esta genera un duplicado del proceso actual. El duplicado comparte los valores actuales de todas las variables, ficheros y otras estructuras de datos. La llamada a fork retorna al proceso padre el identificador del proceso hijo y retorna un cero al proceso hijo.

PID

Las siglas PID, del inglés Process IDentifier, se usan para referirse al identificador de proceso.

La función getppid

El hijo puede obtener el identificador del proceso padre llamando a la función getppid.

La variable $$

La variable especial $$ contiene el PID del proceso actual. Es de sólo lectura.

Ejemplo de uso de fork

Veamos un ejemplo de uso de estas funciones:

lhp@nereida:~/Lperl/src$ cat -n fork2.pl
 1  #!/usr/local/bin/perl -w
 2  use strict;
 3
 4  print "Antes del fork: PID=$$\n";
 5
 6  my $a = 4;
 7  my $ra = \$a;
 8  my $child = fork();
 9  die "Falló el fork: $!" unless defined $child;
10
11  if ($child > 0) { # proceso padre
12    print "Aqui proceso padre: PID=$$, hijo=$child \$a = $a\n";
13    $a = 5; # Modificación local al padre
14    print "Aqui proceso padre después de a = 5: ",
15          "PID=$$, hijo=$child \$a = $a, \$ra = $ra \$ra -> $$ra\n";
16  } else { #proceso hijo
17    my $ppid = getppid();
18    print "Aqui proceso hijo: PID=$$, padre=$ppid \$a = $a, \$ra = $ra \$ra -> $$ra\n";
19  }

Ejecución

Al ejecutar el programa anterior se obtiene la salida:

hp@nereida:~/Lperl/src$ fork2.pl
Antes del fork: PID=11692
Aqui proceso padre: PID=11692, hijo=11693 $a = 4
Aqui proceso padre después de a = 5: PID=11692, hijo=11693 $a = 5, $ra = SCALAR(0x815033c) $ra -> 5
Aqui proceso hijo: PID=11693, padre=11692 $a = 4, $ra = SCALAR(0x815033c) $ra -> 4
Obsérvese como las replicas de $ra contienen idénticas direcciones pero apuntan a segmentos disjuntos.

Grupos de procesos

Los procesos hijo pueden a su vez generar nuevos hijos, creandose así una jerarquía de procesos. dicha jerarquía recibe el nombre de grupo de procesos. Todos los miembros de un grupo comparten los ficheros que estaban abiertos cuando su padre los creó. En particular comparten STDIN, STDOUT y STDERR.

La Muerte de los Huérfanos

Cuando el proceso padre muere antes que el proceso hijo los sistemas unix suelen producir una adopción automática: el proceso es ''reparented'' al proceso init (PID 1).



Subsecciones
Casiano Rodríguez León
2010-03-22
A NAME="tex2html15" HREF="refguide.pdf">pbpblogsgoogle code project hosting
Sig: screen Sup: SSH: Secure Shell Ant: Arrancando Múltiples Sesiones SSH
Casiano Rodríguez León
2011-02-21
dríguez León
2011-02-21 HTML> kgroundIface setWallpaper /tmp/393_5052_2.jpg casiano@europa:~$ dcop kdesktop KBackgroundIface setColor '#E444F2' true casiano@europa:~$ dcop kdesktop KBackgroundIface setColor '#68F20B' true

Ejemplo: knotes

He aqui un ejemplo que ilustra como establecer notas post-it con knotes desde la shell:

$dcop knotes KNotesIface
QCStringList interfaces()
QCStringList functions()
int newNote(QString name,QString text)
int newNoteFromClipboard(QString name)
ASYNC showNote(int noteId)
ASYNC hideNote(int noteId)
ASYNC killNote(int noteId)
QMap notes()
ASYNC setName(int noteId,QString newName)
ASYNC setText(int noteId,QString newText)
QString text(int noteId)
ASYNC sync(QString app)
bool isNew(QString app,int noteId)
bool isModified(QString app,int noteId)

Vamos a añadir una nota:

dcop knotes KNotesIface newNote "Titulo de la Nota" "Corregir exámenes"

Ahora veamos las notas que tenemos disponibles:

lusasoft@LusaSoft:~/src/perl/perltesting/dcop$ dcop knotes KNotesIface notes
libkcal-2096876672.442->Titulo de la Nota
libkcal-461202155.843->03-05-09 15:06
libkcal-962646955.232->Una nota

Conexiones SSH con konsole

lusasoft@LusaSoft:~/src/perl/perltesting/dcop$ cat -n dcop_control.pl
 1  #!/usr/bin/perl -w
 2  use strict;
 3  use Log::Log4perl qw(:easy);
 4  use Time::HiRes qw(usleep);
 5  use Backtick::AutoChomp;
 6
 7  Log::Log4perl->easy_init($DEBUG);
 8  my $logger = Log::Log4perl->get_logger();
 9
10  my @servers = qw{orion beowulf europa};
11
12  my $konsole= `dcopstart konsole-script`;
13
14  $logger->warn("can't maximize window\n") if system("dcop $konsole konsole-mainwindow#1 maximize");
15
16  my $thissession= qx{dcop $konsole konsole currentSession};
17
18  # rename this window/session
19  system qq{dcop $konsole $thissession renameSession "init"};
20
21  # start a new session tab for each server
22  for  (@servers) {
23    # this output is displayed on the terminal which is running your script
24    $logger->debug("connecting to server: $_");
25
26    # create another konsole tab and save handle in $newsession
27    my $newsession=`dcop $konsole konsole newSession "ssh $_"`;
28
29    # wait for shell startup - raise if needed
30    usleep(1000) while `dcop $konsole $newsession sessionPID` eq 0;
31
32    # rename the new session
33    !system(qq{dcop $konsole $newsession renameSession $_}) or $logger->warn("can't rename new session to $_\n");
34
35    # and start the ssh session
36    !system(qq{dcop $konsole $newsession sendSession "exec ssh $_ @ARGV"}) or $logger->warn("can't exec ssh  $_ @ARGV\n");
37
38  }
39
40  # close the first session window
41  !system(qq{dcop $konsole $thissession closeSession > /dev/null}) or $logger->warn("can't close intial session\n");
42
43  __END__

Véase También



Subsecciones
Casiano Rodríguez León
2011-06-03