Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

fork & pipe

2 réponses
Avatar
Codex Durex
Bonjour,

Voilà, je suis entrain d'essayer de comprendre le fonctionnement de
fork() et de pipe()

Pour fork() j'ai compris comment cela fonctionner mais pipe() présente
encore quelques mystères pour moi.

Je m'explique j'aimerai créer par exemple 5 processus enfants (donc 5 +
1 (parent)).
Pour tenter de comprendre, j'essaie donc pour chaque processus enfants
d'envoyer au père son propre pid.

Je procède comme ceci :

> #!/usr/bin/perl
>
> use strict;
> use warnings;
> use IO::Handle;
> use constant {
> MAX_PROCESS => 2
> };
>
> my ($child, $pid, @childs, @process_list, $child_pid);
>
> pipe(FROM_CHILD, TO_PARENT);
>
> for (1...MAX_PROCESS) {
> $pid = fork();
> if ($pid) { # Parent code
> push(@childs, $pid);
> close TO_PARENT;
> $child_pid = <FROM_CHILD>;
> close FROM_CHILD;
> print "My child's pid : $child_pid \n";
> push(@process_list, $child_pid);
> }
> else { #child
> close FROM_CHILD;
> print TO_PARENT $$;
> close TO_PARENT;
> print "New process launched (",$_,"/",MAX_PROCESS,"): [$$]\n";
> exit(0);
> }
> }
>
> print "[$$] -> @process_list \n";
>
> foreach (@childs) {
> waitpid($_,0);
> }


Voici ce que j'obtiens :

> maanes@void:~/workspace$ ./fork.pl
> New process launched (1/2): [32497]
> My child's pid : 32497
> print() on closed filehandle TO_PARENT at ./fork.pl line 26.
> New process launched (2/2): [32498]
> readline() on closed filehandle FROM_CHILD at ./fork.pl line 19.
> Use of uninitialized value in concatenation (.) or string at ./fork.pl line 21.
> My child's pid :
> Use of uninitialized value in join or string at ./fork.pl line 33.
> [32496] -> 32497

Donc pour le premier enfant cela fonctionne correctement.
J'avoue ne pas trop comprendre pourquoi j'ai cette erreur.
Je suppose qu'il y a une sorte de 'collisions' entre les handles du pipe
ou quelques chose comme ça mais je ne vois pas trop comment faire
autrement...
Si quelqu'un pouvait m'éclaircir...

Merci

2 réponses

Avatar
bgy
J'ai eu ma réponse sur la version anglaise (comp.lang.perl.misc)

Voici donc le code fonctionnement pour ceux qui le souhaitent.

#!/usr/bin/perl

use strict;
use warnings;
use IO::Handle;
use constant {
MAX_PROCESS => 10
};

my ($child, $pid, @childs, @process_list, $child_pid);


for (1...MAX_PROCESS) {
pipe(FROM_CHILD, TO_PARENT);
$pid = fork();
if ($pid) { # Parent code
push(@childs, $pid);
close TO_PARENT;
$child_pid = <FROM_CHILD>;
chomp($child_pid);
close FROM_CHILD;
print "My child's pid : $child_pid n";
push(@process_list, $child_pid);
}
else { #child
close FROM_CHILD;
print TO_PARENT $$,"n";
close TO_PARENT;
print "New process launched (",$_,"/",MAX_PROCESS,"): [$$]n";
sleep 5;
exit(0);
}
}

print "[$$] -> @process_list n";

foreach (@childs) {
waitpid($_,0);
}


Avatar
Jogo
Sur fr.comp.lang.perl, Codex Durex disait :

J'avoue ne pas trop comprendre pourquoi j'ai cette erreur.



Tout simplement parce que ton pipe n'est pas dans la boucle. Du coup
quand le père arrive à la seconde itération les deux extrémité du pipe
ont été fermés.

Si tu ne veux utiliser qu'une pipe :

pipe(FROM_CHILD, TO_PARENT);

for (1...MAX_PROCESS) {
$pid = fork();
if ($pid) { # Parent code
push(@childs, $pid);
}
else { #child
close FROM_CHILD;
print TO_PARENT "$$n";
close TO_PARENT;
print "New process launched (",$_,"/",MAX_PROCESS,"): [$$]n";
exit(0);
}
}

close TO_PARENT;
while (<FROM_CHILD>) {
print "received $_";
}

--
Fufe n'est pas la vraie vie, c'est un espace de travail.
Il ne sert à rien de relativiser, c'est hors de propos.
-+- FF dans fufe - Neuneu=MC² -+-