Bon, c'est un truc tout con et classique (quoique c'est plutôt le
forkbomb avec un while qui est souvent traité) puisque j'en ai déjà
entendu parler ici et là, mais je n'arrive pas à *vraiment* comprendre.
Avec un programme C de ce style (pas forcément ultra-respectueux des
normes, mais dans ce contexte, je pense que ça n'est pas gênant) :
int i, p;
int
main ()
{
for (i = 0; i < 2; i++)
{
p = fork ();
if (p == 0)
printf ("F%d ", i);
else
printf ("P%d ", i);
}
return 0;
}
j'obtiens 8 affichages alors que je m'attends à en avoir 6. Mon
raisonnement : au départ, un processus, i vaut 0. Après le fork, une
copie est créée, i y vaut également 0 ; chacun fait un affichage. Chaque
processus continue et passe au tour où i vaut 1. Chacun recrée une
copie, donc 4 processus en tout, et 4 affichages. Chacun s'arrête
ensuite puisque la boucle est finie. Donc pourquoi 8 affichages ? J'ai
l'impression que la boucle reprend à 0, mais dans ce cas, l'ensemble du
truc ne devrait jamais s'arrêter !
Idem avec i < 3, on obtient 24 affichages et non pas 14, bref il y a un
motif en n*2^n mais je n'arrive pas à le prouver rigoureusement puisque
je m'obstine à faire le somme des 2^i.
Avec un programme C de ce style (pas forcément ultra-respectueux des normes, mais dans ce contexte, je pense que ça n'est pas gênant) :
int i, p;
int main () { for (i = 0; i < 2; i++) { p = fork (); if (p == 0) printf ("F%d ", i); else printf ("P%d ", i); } return 0; }
Ajoute un fflush(stdout); après les printf, à tout hasard.
Pascal Bourguignon
Damien Wyart writes:
Bon, c'est un truc tout con et classique (quoique c'est plutôt le forkbomb avec un while qui est souvent traité) puisque j'en ai déjà entendu parler ici et là, mais je n'arrive pas à *vraiment* comprendre.
Avec un programme C de ce style (pas forcément ultra-respectueux des normes, mais dans ce contexte, je pense que ça n'est pas gênant) :
int i, p;
int main () { for (i = 0; i < 2; i++) { p = fork (); if (p == 0) printf ("F%d ", i); else printf ("P%d ", i); } return 0; }
j'obtiens 8 affichages alors que je m'attends à en avoir 6. Mon raisonnement : au départ, un processus, i vaut 0. Après le fork, une copie est créée, i y vaut également 0 ; chacun fait un affichage. Chaque processus continue et passe au tour où i vaut 1. Chacun recrée une copie, donc 4 processus en tout, et 4 affichages. Chacun s'arrête ensuite puisque la boucle est finie. Donc pourquoi 8 affichages ? J'ai l'impression que la boucle reprend à 0, mais dans ce cas, l'ensemble du truc ne devrait jamais s'arrêter !
Idem avec i < 3, on obtient 24 affichages et non pas 14, bref il y a un motif en n*2^n mais je n'arrive pas à le prouver rigoureusement puisque je m'obstine à faire le somme des 2^i.
Merci pout tout éclaircissement...
J'obtiens le résultat attendu:
[ tmp]$ cat f.c #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> int main (void){ int i; int p; int level=0; for(i=0;i<2;i++){ p=fork(); if(p==0){ level++; printf("%*s child: i=%d, ppid=%d, pid=%d n", level*3,"",i,getppid(),getpid()); fflush(stdout);} else{ printf("%*s parent: i=%d, my pid=%d, forked child pid=%d n", level*3,"",i,getpid(),p); fflush(stdout);}} return(0); } [ tmp]$ gcc -o f f.c -Wall -Werror -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Wconversion -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline [ tmp]$ ./f parent: i=0, my pid0814, forked child pid0815 parent: i=1, my pid0814, forked child pid0816 child: i=0, ppid0814, pid0815 parent: i=1, my pid0815, forked child pid0817 child: i=1, ppid0814, pid0816 child: i=1, ppid=1, pid0817 [ tmp]$ ^^^^^^ Le processus 30816 doit s'être terminé avant que le processus 30817 n'ait appelé getppid().
"You can tell the Lisp programmers. They have pockets full of punch cards with close parentheses on them." --> http://tinyurl.com/8ubpf
Damien Wyart <damien.wyart@free.fr> writes:
Bon, c'est un truc tout con et classique (quoique c'est plutôt le
forkbomb avec un while qui est souvent traité) puisque j'en ai déjà
entendu parler ici et là, mais je n'arrive pas à *vraiment* comprendre.
Avec un programme C de ce style (pas forcément ultra-respectueux des
normes, mais dans ce contexte, je pense que ça n'est pas gênant) :
int i, p;
int
main ()
{
for (i = 0; i < 2; i++)
{
p = fork ();
if (p == 0)
printf ("F%d ", i);
else
printf ("P%d ", i);
}
return 0;
}
j'obtiens 8 affichages alors que je m'attends à en avoir 6. Mon
raisonnement : au départ, un processus, i vaut 0. Après le fork, une
copie est créée, i y vaut également 0 ; chacun fait un affichage. Chaque
processus continue et passe au tour où i vaut 1. Chacun recrée une
copie, donc 4 processus en tout, et 4 affichages. Chacun s'arrête
ensuite puisque la boucle est finie. Donc pourquoi 8 affichages ? J'ai
l'impression que la boucle reprend à 0, mais dans ce cas, l'ensemble du
truc ne devrait jamais s'arrêter !
Idem avec i < 3, on obtient 24 affichages et non pas 14, bref il y a un
motif en n*2^n mais je n'arrive pas à le prouver rigoureusement puisque
je m'obstine à faire le somme des 2^i.
Merci pout tout éclaircissement...
J'obtiens le résultat attendu:
[pjb@thalassa tmp]$ cat f.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main (void){
int i;
int p;
int level=0;
for(i=0;i<2;i++){
p=fork();
if(p==0){
level++;
printf("%*s child: i=%d, ppid=%d, pid=%d n",
level*3,"",i,getppid(),getpid());
fflush(stdout);}
else{
printf("%*s parent: i=%d, my pid=%d, forked child pid=%d n",
level*3,"",i,getpid(),p);
fflush(stdout);}}
return(0); }
[pjb@thalassa tmp]$ gcc -o f f.c
-Wall -Werror -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align
-Wwrite-strings -Wconversion -Wstrict-prototypes -Wmissing-prototypes
-Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline
[pjb@thalassa tmp]$ ./f
parent: i=0, my pid0814, forked child pid0815
parent: i=1, my pid0814, forked child pid0816
child: i=0, ppid0814, pid0815
parent: i=1, my pid0815, forked child pid0817
child: i=1, ppid0814, pid0816
child: i=1, ppid=1, pid0817
[pjb@thalassa tmp]$
^^^^^^ Le processus 30816 doit s'être terminé avant
que le processus 30817 n'ait appelé getppid().
Bon, c'est un truc tout con et classique (quoique c'est plutôt le forkbomb avec un while qui est souvent traité) puisque j'en ai déjà entendu parler ici et là, mais je n'arrive pas à *vraiment* comprendre.
Avec un programme C de ce style (pas forcément ultra-respectueux des normes, mais dans ce contexte, je pense que ça n'est pas gênant) :
int i, p;
int main () { for (i = 0; i < 2; i++) { p = fork (); if (p == 0) printf ("F%d ", i); else printf ("P%d ", i); } return 0; }
j'obtiens 8 affichages alors que je m'attends à en avoir 6. Mon raisonnement : au départ, un processus, i vaut 0. Après le fork, une copie est créée, i y vaut également 0 ; chacun fait un affichage. Chaque processus continue et passe au tour où i vaut 1. Chacun recrée une copie, donc 4 processus en tout, et 4 affichages. Chacun s'arrête ensuite puisque la boucle est finie. Donc pourquoi 8 affichages ? J'ai l'impression que la boucle reprend à 0, mais dans ce cas, l'ensemble du truc ne devrait jamais s'arrêter !
Idem avec i < 3, on obtient 24 affichages et non pas 14, bref il y a un motif en n*2^n mais je n'arrive pas à le prouver rigoureusement puisque je m'obstine à faire le somme des 2^i.
Merci pout tout éclaircissement...
J'obtiens le résultat attendu:
[ tmp]$ cat f.c #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> int main (void){ int i; int p; int level=0; for(i=0;i<2;i++){ p=fork(); if(p==0){ level++; printf("%*s child: i=%d, ppid=%d, pid=%d n", level*3,"",i,getppid(),getpid()); fflush(stdout);} else{ printf("%*s parent: i=%d, my pid=%d, forked child pid=%d n", level*3,"",i,getpid(),p); fflush(stdout);}} return(0); } [ tmp]$ gcc -o f f.c -Wall -Werror -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Wconversion -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline [ tmp]$ ./f parent: i=0, my pid0814, forked child pid0815 parent: i=1, my pid0814, forked child pid0816 child: i=0, ppid0814, pid0815 parent: i=1, my pid0815, forked child pid0817 child: i=1, ppid0814, pid0816 child: i=1, ppid=1, pid0817 [ tmp]$ ^^^^^^ Le processus 30816 doit s'être terminé avant que le processus 30817 n'ait appelé getppid().
Ajoute un fflush(stdout); après les printf, à tout hasard.
En effet, c'est tout de suite mieux. Ca me rassure, mon raisonnement était bon...
Donc c'est juste un effet de bord bizarre des E/S tamponnées ? Ca le fait que sur Linux ou ?
-- DW
Stephane Dupille
Donc c'est juste un effet de bord bizarre des E/S tamponnées ?
Oui.
Ca le fait que sur Linux ou ?
Non, ça existe sur plein de système et pas que des jeunes. Je me souviens même d'un programme du genre :
int main (int argc, char **argv) { fork () ; printf ("42n") ; fork () ; printf ("42n") ; }
où le nombre de 42 n'est pas le même selon qu'on redirige stdout vers un pipe ou un terminal (donc les appels "./a.out" et "./a.out | more" ne donne pas la même chose). D'ailleurs, ça non-marche sur mon BSD :
-- S> Je cherche aussi des adresses de lieux contenant des fossiles dans S> la région parisienne http://www.senat.fr/ -+- DP in <http://www.le-gnu.net> : La dianurette et les fossiles -+-
Donc c'est juste un effet de bord bizarre des E/S tamponnées ?
Oui.
Ca le fait que sur Linux ou ?
Non, ça existe sur plein de système et pas que des jeunes. Je me
souviens même d'un programme du genre :
int main (int argc, char **argv)
{
fork () ;
printf ("42n") ;
fork () ;
printf ("42n") ;
}
où le nombre de 42 n'est pas le même selon qu'on redirige stdout
vers un pipe ou un terminal (donc les appels "./a.out" et "./a.out |
more" ne donne pas la même chose). D'ailleurs, ça non-marche sur mon
BSD :
--
S> Je cherche aussi des adresses de lieux contenant des fossiles dans
S> la région parisienne
http://www.senat.fr/
-+- DP in <http://www.le-gnu.net> : La dianurette et les fossiles -+-
Donc c'est juste un effet de bord bizarre des E/S tamponnées ?
Oui.
Ca le fait que sur Linux ou ?
Non, ça existe sur plein de système et pas que des jeunes. Je me souviens même d'un programme du genre :
int main (int argc, char **argv) { fork () ; printf ("42n") ; fork () ; printf ("42n") ; }
où le nombre de 42 n'est pas le même selon qu'on redirige stdout vers un pipe ou un terminal (donc les appels "./a.out" et "./a.out | more" ne donne pas la même chose). D'ailleurs, ça non-marche sur mon BSD :
-- S> Je cherche aussi des adresses de lieux contenant des fossiles dans S> la région parisienne http://www.senat.fr/ -+- DP in <http://www.le-gnu.net> : La dianurette et les fossiles -+-
DINH Viêt Hoà
où le nombre de 42 n'est pas le même selon qu'on redirige stdout vers un pipe ou un terminal (donc les appels "./a.out" et "./a.out | more" ne donne pas la même chose). D'ailleurs, ça non-marche sur mon BSD :
vers un pipe, tu es en bufferisation avec flush après une certaine taille de données. vers un terminal, tu es en bufferisation avec flush à chaque saut de ligne.
-- DINH V. Hoa,
"Et alors, les parents d'Odile ? Ils sont trop cool, et tout ce qu'ils veulent, c'est qu'elle sorte en boîte tous le soirs [...] et ils militent contre les maths à l'école ?" -- Virginie Despentes
où le nombre de 42 n'est pas le même selon qu'on redirige stdout
vers un pipe ou un terminal (donc les appels "./a.out" et "./a.out |
more" ne donne pas la même chose). D'ailleurs, ça non-marche sur mon
BSD :
vers un pipe, tu es en bufferisation avec flush après une certaine
taille de données.
vers un terminal, tu es en bufferisation avec flush à chaque saut de
ligne.
--
DINH V. Hoa,
"Et alors, les parents d'Odile ? Ils sont trop cool, et tout ce qu'ils
veulent, c'est qu'elle sorte en boîte tous le soirs [...]
et ils militent contre les maths à l'école ?" -- Virginie Despentes
où le nombre de 42 n'est pas le même selon qu'on redirige stdout vers un pipe ou un terminal (donc les appels "./a.out" et "./a.out | more" ne donne pas la même chose). D'ailleurs, ça non-marche sur mon BSD :
vers un pipe, tu es en bufferisation avec flush après une certaine taille de données. vers un terminal, tu es en bufferisation avec flush à chaque saut de ligne.
-- DINH V. Hoa,
"Et alors, les parents d'Odile ? Ils sont trop cool, et tout ce qu'ils veulent, c'est qu'elle sorte en boîte tous le soirs [...] et ils militent contre les maths à l'école ?" -- Virginie Despentes