fork() - étudier la mémoire [C] - C - Programmation
Marsh Posté le 29-12-2004 à 11:13:01
avec gdb tu va faire du pas a pas. Tu vas voir chaque passage dans tes boucles for.
j'ai pas verifie mais je ne sais pas comment il se comporte notre ami gdb dans un prg multi process.
C'est sur que tu peux regarder les valeurs des variables et avoir leur implantation memoire (virtuelle ?) mais au dela de ca.. auras tu le pid ?
j'ai toujours eu en tete qu'a l'exec du fork le processus fils a son propre espace memoire virtuelle qui est une copie du contexte du parent.
Il connait les descripteurs ke le parent connait, variables, etc.
Mais les deux espaces memoire virtuelle des processus sont distincts physiquement.
Ca me parait d'ailleurs logique puisque suivant que l'ordonnanceur donne la main au fils ou au pere le retour du fork est different.
Enfin, la fonction fork est kan meme sencee dupliquer le process. C d'ailleurs explicite par le cas d'erreur possible en sortie :
Code :
|
j'espere avoir repondu a ta question.. meme si ce n'est pas sur cette voie que tu cherchais.
Marsh Posté le 29-12-2004 à 12:51:22
Au moment où le fork est fait, seule une petite partie de la mémoire est dupliquée. En fait la gestion de la mémoire fonctionne par bloc et dés qu'un bloc est différent pour les deux processus il est dupliqué mais tant que le bloc est identique pour les deux processus il ne sera pas dupliqué.
Donc tant qu'il n'est pas nécessaire de dupliquer une zone mémoire elle ne le sera pas.
J'espère ne pas avoir dit trop de conneries.
Marsh Posté le 29-12-2004 à 12:53:08
Sinon "man fork" explique bien ce qu'il se passe :
FORK(2) Manuel du programmeur Linux FORK(2) |
Marsh Posté le 29-12-2004 à 14:06:04
Mais comment pouvoir observer visuellement ce phénomène ?
Marsh Posté le 29-12-2004 à 21:29:25
Personne n'a d'idée
Marsh Posté le 29-12-2004 à 21:33:41
averc un sleep.
Le processus père crée un grand tableau (plusieurs pagesà qu'il rempli. On va voir sa mémoire monter.
Puis il forke, le fils va faire des modifications au fur et à mesure dans le grand tableau au hasard (avec un sleep entre chaque écriture pour laisser le temps de voir), et chaques fois qu'il écrit dans une page ou il n'a pas encore écrit, sa mémoire prise augmente.
Par contre, je me souviens plus de la taille d'une page mémoire sous linux. Il me semble qu'elle fait 4ko ou 4Mo, suivant le système d'addressage utilisé.
Marsh Posté le 30-12-2004 à 00:08:39
Elle est de 4ko sur processeur 32bit et 8ko sur 64bit
Marsh Posté le 30-12-2004 à 03:59:35
4Ko en standard, 4Mo en mode PAE pour les x86, mais à vérifier si en PAE on le choix ou pas.
je crois qu'en x86-64 les pages font 4Mo.
Marsh Posté le 30-12-2004 à 04:00:22
nodus >> tu parles du x68-64, ou des PowerPC par exemple ?
(je peux être complètement à coté de la plaque)
Marsh Posté le 30-12-2004 à 14:37:22
Pour le 8ko c'est sur des sparcs, j'imagine que ça doit être pareil sur les autres architectures 64bit.
Marsh Posté le 30-12-2004 à 15:11:56
H.S.
Sous HP-UX, chaque programme peut avoir une valeur différente, entre 4K et 256M (ça c'est de la page!) avec ça:
http://docs.hp.com/en/B2355-90689/chatr.1.html
Marsh Posté le 30-12-2004 à 15:49:39
Lam's a écrit : H.S. |
oui & non, c'est sur une machine en PA-RISC, ou un Itanium (qui est je crois compatible naturellement avec les binaires PA-RISC).
la taille des pages est complétement dépendantes des capacitées du MMU du CPU. ie ce n'est pas une caractéristique propre à un OS.
Marsh Posté le 30-12-2004 à 15:54:22
autant pour moi, en x86-64 même en long mode, les pages restent à 4Ko:
http://lwn.net/2001/features/OLS/pdf/pdf/x86-64.pdf
Marsh Posté le 30-12-2004 à 15:59:33
bjone a écrit : oui & non, c'est sur une machine en PA-RISC, ou un Itanium (qui est je crois compatible naturellement avec les binaires PA-RISC). |
D'une part, c'est effectivement sur PA-RIC.
D'autre part, effectivement, sur x86 c'est soit 4K soit 4M. L'itanium tourne à 16K, mais il faudrait que je vérifie (j'ai tendance à me mélanger les pinceaux entre la segmentation et le paging).
Marsh Posté le 30-12-2004 à 18:43:51
Et sur architecture Power, les pages font 4kB ou 16MB, au choix. Et bientot il y aura des pages de 16kB et 16GB.
Marsh Posté le 30-12-2004 à 19:18:13
16Go de page ? mmm.... c'est voir à très long terme (ou alors pour du mapping d'espace de périph)
Marsh Posté le 30-12-2004 à 19:50:05
Par contre en ayant exécuté mon programme j'ai remarqué que le printf n'était pas exécuté, c'est normal selon vous
Marsh Posté le 12-02-2005 à 19:38:10
darkoli a écrit : Au moment où le fork est fait, seule une petite partie de la mémoire est dupliquée. En fait la gestion de la mémoire fonctionne par bloc et dés qu'un bloc est différent pour les deux processus il est dupliqué mais tant que le bloc est identique pour les deux processus il ne sera pas dupliqué. |
Donc si je comprends bien :
Mettons que j'initialise un grand tableau de milliers d'entrées.
Je fais un fork. Le processus fils ne fera que consulter ce tableau, jamais il n'écrira dedans. Conclusion : le tableau ne sera pas dupliqué et sera simplement partagé entre les 2 processus ce qui évite un grand gaspillage de mémoire?
Si oui ç'est très intéressant, car je comptais utiliser une shared memory pour éviter la duplication du tableau. Mais comme il n'est pas dupliqué, pas besoin d'avoir recours à ce genre d'astuce.
J'ai bien tout compris?
Marsh Posté le 12-02-2005 à 20:17:53
tout à fait mon colonel...
sauf que si le processus père écrit dans le tableau (dumoins l'espace alloué), le fils verra toujours les anciennes données.
donc si tu veux que le père produise, et le fils consomme, ça marchera pas.
Marsh Posté le 15-02-2005 à 21:38:46
Il me semble que des erreurs on été dite...
D'après ce que je sais et ce que j'ai expérimenté sur cette fonction
fork() creer donc un processus identique à celui du pere...
Le fils hérite des fichiers ouverts, mais n'a pas la même zone mémoire alouée, ce qu'il fait qu'il n'ont aucune zone mémoire commune...
Pour faire communiqué deux processus ayant un lien de parenté, il existe les ipc
=> les pipes
=> les files de messages
=> les sémaphores (pour la synchronisation)
=> les mémoires partagées (shared memory)
=> connexion par réseau
chaque processus à donc son propre SEGMENT de DONNEE, SEGMENT de PILE et SEGMENT de CODE (DS, SS et CS)...
donc je suis kazi certain à 99% qu'au départ, le fils n'aura pas accès aux zone mémoire du père puisque ce n'est pas la même zone mémoire qui lui ait allouée...
j'ai eu l'occasion de testé cela il y a deux mois de ça sur une grosse application UNIX que j'ai du faire...
Donc si tu veux vraiment faire communiqué les deux processus, je te conseille la mémoire partagée, voir les files de messages...
Marsh Posté le 15-02-2005 à 21:45:20
Merci pour ces lumières mais en fait pour des questions d'optimisation, la plupart des implémentations ne procédent pas à une copie compléte des données/pile/tas du père sachant qu'un fork est souvant suivi par un exec. Elles utilisent à la place une technique appelée copy-on-write (COW) : elles sont partagées par le père et le fils et ce n'est que quand l'un des 2 tente de modifier l'une de ces régions que le noyau fait une copie de cette région seulement.
Et si tu fais un vfork là le fils fonctionne dans l'espace d'adressage du père, c'est super rigolo.
Marsh Posté le 16-02-2005 à 20:41:57
ah tiens si j'avais su ça avant je crois que ça m'aurais facilité pas mal de truc pour l'examen...
Marsh Posté le 29-12-2004 à 10:02:36
J'aimerais voir un peu comment se fait la gestion de la mémoire lors d'un fork(). On m'a dit qu'aprés le fork le processus fils partage les zones mémoires du père tant que l'un de deux ne la modifie pas. Dans le cas d'une modification le fils créérais une zone propre à lui-même. Pour cela j'ai écris un petit programme.
Le problème est qu'il est bien trop rapide lorsque j'essaie de visualiser son exécution avec top (sous linux), est-ce qu'avec gdb j'arriverais à mieux voir le phénomène ?
Voici le prog:
---------------
Et toi, tu crois que les ours polaires vont chier dans les bois ?