D'après souviron34, toutes.
D'après moi, aucune (c'est de lui que je tenais les "certaines"), sauf peut-être celle de cygwin, et encore je suis loin d'en être sur.
Version imprimable
D'après souviron34, toutes.
D'après moi, aucune (c'est de lui que je tenais les "certaines"), sauf peut-être celle de cygwin, et encore je suis loin d'en être sur.
Et comment une telle chose pourrait-elle être implémentée?
Remarque, le re-jeu serait très pratique pour le débogage. Mais parle t-on de systèmes déterministes?
Note : Le re-jeu est une méthode de débogage en programmation logique (CLP).
C'est à lui qu'il faut le demander, pas à moi.
Ça me parait aussi logique qu'à toi, tu sais...
tres simple de verifier...
Lit un petit fichier juste avant et stocke-le dans un tableau de chaines allouees dynamiquement...
Si c'est la "copie", les adresses des chaines devraient etre les memes, si je vous suis...
Si il refait le code, les adresses seront differentes :D
(a mon avis, si c'etait la copie, ca marcherait pas, car pas de memoire partagee , or on a 2 processus differents... )
Je n'ai pas de système unixoïde sous la main, mais je suis persuadé que c'est de la copie, et si, ça marcherait:
Deux processus peuvent référencer exactement la même adresse virtuelle, et pourtant "voir" deux zones mémoire différentes.
Bien sûr que les adresses sont les mêmes! On ne va quand même pas perde notre temps à faire des expériences absurdes dont on connait le résultat par avance pour te faire plaisir.
Pas forcément. Au contraire, je parierai que l'allocation dynamique est déterministe.
Tu ne comprends toujours pas ce que fait fork().
J'ai fait des tests, et je n'arrive pas à avoir des pointeurs différents.
Par exemple avec ce code :
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> #include <sys/stat.h> #include <fcntl.h> int main(int argc, char **argv) { char *texte[10] = {0}; int i = 0; for(i = 0; i < 10; i++) { texte[i] = (char *)malloc(1 + i); } if(fork() < 0) { exit(1); } for(i = 0; i < 10; i++) { printf("%d : texte[%d] = %p\n", getpid(), i, texte[i]); } return 0; }
Rajoute un affichage de texte juste avant le fork(), s'il te plait, juste pour faire joli et nous dire si le texte est affiché deux fois (il faut s'attendre à tout, mais je parierais que non)...
Au début j'avais essayé ceci :
et cela donne :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> int main(int argc, char **argv) { void * foo = 0; printf("%d : foo = %p\n", getpid(), foo); foo = malloc(42); if(fork() < 0) { exit(1); } printf("%d : foo = %p\n", getpid(), foo); return 0; }
Je me paluche le man de fork en attendant.Code:
1
2
3 1737 : foo = (nil) 1738 : foo = 0x804a008 1737 : foo = 0x804a008
Par contre,
si tu as un exemple, ça m'éclairerait.Citation:
Deux processus peuvent référencer exactement la même adresse virtuelle, et pourtant "voir" deux zones mémoire différentes.
Pourquoi?
Si je te dis que printf("%d",2+2) affiche 42, tu fais le test aussi?
Tu veux dire :
?
- chaque exécution du programme affiche deux fois la même chose, ou
- toutes les exécutions du programme affichent exactement la même chose (= le test ne teste rien du tout)
Le système d'exploitation est fait pour que par défaut, chaque programme se croie seul sur le système.
C'est une des raisons pour lesquelles l'adressage est virtuel : Un programme peut voir quelque chose à l'adresse virtuelle X, mais la "vraie" adresse en mémoire, ou dans le fichier de pagination, est seulement connue du système d'exploitation.
Ainsi, les variables globales d'un programme pourraient avoir une adresse virtuelle fixe (par exemple, un int se trouvant toujours à l'adresse virtuelle 0x00000004). Si tu fais tourner deux programmes, chacun verra sa variable à l'adresse virtuelle 0x00000004, mais les vraies adresses seront différentes (par exemple, l'un peut être voir les adresses réelles 1000 à 1999, tandis que l'autre verra les adresses réelles 2000 à 2999).
Et en plus, avec les histoires de pagination, mise de la mémoire sur le disque et autre, ces adresses réelles peuvent changer au cours du temps. Mais du point de vue du processus, l'adresse virtuelle ne change pas.
Aussi, la "mémoire partagée" est une fonction spéciale du système d'exploitation, qui donne à deux processus l'accès à la même adresse réelle (qui, en fait, peut être représentée par deux adresses virtuelles différentes).
Là, 'faut expliquer ton raisonnement...Citation:
le pid change dans son print, ce qui veut dire que chaque programme est reexecute....
ok , desole j'avais lu trop vite.. :oops:
Un exemple qui devrait bien tester:
Avec un code de ce genre, si le code est ré-exécuté, on aura des valeurs aléatoires différentes.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #define SIZE 20 int main() { srand(time) int pidAvant = getpid(); int val[SIZE] for(i=0 ; i<SIZE ; i++) val[i] = rand(); puts("fork in 2 seconds"); sleep(2); /*pour forcer srand(time) à régler une autre "graine"*/ fork(); printf("Avant=%d Après=%d", pidAvant, getpid()); for(i=0 ; i<SIZE ; i++) printf("process%d[ %d ] : %d", getpid(), i, val[i]); }
Et à mon avis, tout comme celui de corrector, elles devraient être identiques.
Edit: Je rentre chez moi et j'ai 1h30 de transports. À plus!
Rhaa j'ai plus d'unixoide à disposition pour tester ça. Mais je pense qu'on aura les mêmes valeurs dans le père et dans le fils. Parce que tant qu'un test ne travaille que sur la mémoire ben on ne prouve rien vu que chaque processus reçoit une copie de la mémoire au moment du fork. Or quand le fork est lancé, le tableau a déjà été rempli.
En fait, plus je réfléchis et plus je me dis que du point de vue des programmeurs systèmes, il serait plus facile de faire commencer le fils au moment du fork que de lui faire rejouer tout le code exécuté avant tout en lui demandant de ne pas changer les valeurs trouvées lors de la première exécution.
D'ailleurs, si je tape
Est ce que le fils va vraiment rejouer tout le code et attendre lui-aussi connement 5mn avant d'afficher "hello" ???Code:
1
2
3
4 sleep(300); printf("Depart\n"); fork(); printf("Fin\n");
Bon, j'ai fait le test sur mon vieux Ubuntu 5.04:
Et la sortie:Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 #include <stdio.h> #include <unistd.h> #include <time.h> #include <math.h> #define SIZE 10 int main() { int pidAvant = getpid(); int val[SIZE]; size_t i; srand((int)time(NULL)); for(i=0 ; i<SIZE ; i++) val[i] = rand(); puts("fork in 2 seconds"); sleep(2); /*pour forcer srand(time) à régler une autre "graine"*/ fork(); printf("Avant=%d Après=%d\n", pidAvant, getpid()); for(i=0 ; i<SIZE ; i++) printf("process%d[ %d ] : %d\n", getpid(), i, val[i]); return 0; }
Cela montre que non seulement les valeurs sont identiques, mais le "pid avant fork()" est identique également.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 link@ubuntu:~/TestsCpp$ gcc -o testfork TestFork.c link@ubuntu:~/TestsCpp$ ./testfork fork in 2 seconds Avant=8102 AprÚs=8103 process8103[ 0 ] : 688197052 process8103[ 1 ] : 1049773403 process8103[ 2 ] : 413948371 process8103[ 3 ] : 1623950930 process8103[ 4 ] : 755136942 process8103[ 5 ] : 762038674 process8103[ 6 ] : 539295439 process8103[ 7 ] : 1471486800 process8103[ 8 ] : 1637510112 process8103[ 9 ] : 923374679 Avant=8102 AprÚs=8102 process8102[ 0 ] : 688197052 process8102[ 1 ] : 1049773403 process8102[ 2 ] : 413948371 process8102[ 3 ] : 1623950930 process8102[ 4 ] : 755136942 process8102[ 5 ] : 762038674 process8102[ 6 ] : 539295439 process8102[ 7 ] : 1471486800 process8102[ 8 ] : 1637510112 process8102[ 9 ] : 923374679 link@ubuntu:~/TestsCpp$
Cela suffit-il à prouver que fork() ne ré-exécute pas ce que le programme a déjà accompli ?
(de plus, réexécuter le programme serait plus compliqué que la simple duplication de son état...)
Quant à ce que j'avais dit sur cygwin, on peut aussi spéculer que son implémentation de fork(), au lieu de ré-exécuter, crée un processus séparé et recopie "manuellement" l'état du processus précédent, à coup de VirtualAllocEx(), ReadProcessMemory(), WriteProcessMemory()...