fork () appel système et espace mémoire du processus

Je cite “lorsqu’un processus crée un nouveau processus à l’aide d’un appel fork (), seuls les segments de mémoire partagée sont partagés entre le processus parent et le processus enfant récemment créé. Les copies de la stack et du segment sont créées pour le processus nouvellement créé” à partir de solutions “concepts de système d’exploitation” de Silberschatz.

Mais quand j’ai essayé ce programme

#include  #include  #define MAX_COUNT 200 void ChildProcess(void); /* child process prototype */ void ParentProcess(void); /* parent process prototype */ void main(void) { pid_t pid; char * x=(char *)malloc(10); pid = fork(); if (pid == 0) ChildProcess(); else ParentProcess(); printf("the address is %p\n",x); } void ChildProcess(void) { printf(" *** Child process ***\n"); } void ParentProcess(void) { printf("*** Parent*****\n"); } 

le résultat est comme:

 *** Parent***** the address is 0x1370010 *** Child process *** the address is 0x1370010 

parent et enfant imprimant la même adresse qui est dans le tas.

quelqu’un peut-il m’expliquer la contradiction ici. veuillez indiquer clairement quelles sont toutes les choses partagées par le parent et l’enfant dans l’espace mémoire.

Me citer d’un autre fil.

  • Lorsqu’un appel système fork () est émis, une copie de toutes les pages correspondant au processus parent est créée et chargée dans un emplacement mémoire distinct par le système d’exploitation du processus enfant. Mais ce n’est pas nécessaire dans certains cas. Prenons le cas où un enfant exécute un appel système “exec” ou quitte très rapidement après le fork (). Lorsque l’enfant est simplement nécessaire pour exécuter une commande pour le processus parent, il n’est pas nécessaire de copier les pages du processus parent, puisque exec remplace l’espace d’adressage du processus qui l’a appelé avec la commande à exécuter.

    Dans de tels cas, une technique appelée copy-on-write (COW) est utilisée. Avec cette technique, lorsqu’un fork se produit, les pages du processus parent ne sont pas copiées pour le processus enfant. Au lieu de cela, les pages sont partagées entre les processus enfant et parent. Chaque fois qu’un processus (parent ou enfant) modifie une page, une copie distincte de cette page particulière est créée pour ce processus (parent ou enfant) qui a effectué la modification. Ce processus utilisera ensuite la page nouvellement copiée plutôt que la page partagée dans toutes les références futures. L’autre processus (celui qui n’a pas modifié la page partagée) continue d’utiliser la copie d’origine de la page (qui n’est plus partagée). Cette technique s’appelle copie sur écriture puisque la page est copiée lorsqu’un processus y écrit.

  • Aussi, pour comprendre pourquoi ces programmes semblent utiliser le même espace de mémoire (ce qui n’est pas le cas), je voudrais citer une partie de l’ouvrage “Operating Systems: Principles and Practice”.

    La plupart des processeurs modernes introduisent un niveau d’indirection, appelé adresses virtuelles. Avec les adresses virtuelles, la mémoire de chaque processus commence au “même” emplacement, par exemple zéro. Chaque processus pense qu’il a la machine entière pour lui-même, bien que ce ne soit évidemment pas le cas dans la réalité.

    Donc, ces adresses virtuelles sont des traductions d’adresses physiques et ne représentent pas le même espace mémoire physique. Pour laisser un exemple plus pratique, nous pouvons faire un test, si nous compilons et exécutons plusieurs fois un programme qui affiche la direction d’une variable statique, tel que ce programme.

     #include  int main() { static int a = 0; printf("%p\n", &a); getchar(); return 0; } 

    Il serait impossible d’obtenir la même adresse mémoire dans deux programmes différents si nous traitons directement avec la mémoire physique.

    Et les résultats obtenus en exécutant le programme à plusieurs resockets sont …

entrez la description de l'image ici

Oui, les deux processus utilisent la même adresse pour cette variable, mais ces adresses sont utilisées par différents processus et ne font donc pas partie du même espace d’adressage virtuel .

Cela signifie que les adresses sont les mêmes, mais ne pointent pas vers la même mémoire physique. Vous devriez en savoir plus sur la mémoire virtuelle pour comprendre cela.

Vous exécutez probablement votre programme sur un système d’exploitation doté d’une mémoire virtuelle. Après l’appel de fork() , le parent et l’enfant ont des espaces d’adressage distincts. L’adresse 0x1370010 ne pointe donc pas vers le même endroit. Si un processus écrivait dans *x , l’autre processus ne verrait pas le changement. (En fait, il peut s’agir de la même page de mémoire, voire du même bloc dans un fichier d’échange, jusqu’à ce que cela change, mais le système d’exploitation s’assure que la page est copiée dès que le parent ou l’enfant y écrit, donc, autant que le programme puisse dire, il s’agit de sa propre copie.)

L’adresse est la même, mais l’espace d’adressage ne l’est pas. Chaque processus a son propre espace d’adressage, donc 0x1370010 du parent n’est pas identique à 0x1370010 de l’enfant.

Lorsque le kernel fork() le processus en charge, les informations de mémoire copiées héritent des mêmes informations d’adresse car le segment de mémoire est effectivement copié tel quel. Si les adresses étaient différentes, comment metsortingez-vous à jour les pointeurs à l’intérieur de structures personnalisées? Le kernel ne sait rien de ces informations, ces pointeurs seraient alors invalidés. Par conséquent, l’adresse physique peut changer (et en fait le sera souvent même pendant la durée de vie de votre exécutable même sans fork() ing fork() , mais l’adresse logique rest la même.