2010-08-03 8 views
0

J'ai des questions concernant les piles et l'allocation de mémoire dynamique.Question concernant l'allocation de mémoire dynamique

1) Est-ce que le noyau détermine dynamiquement la taille de la pile pendant l'exécution ou définit la taille avant le temps de chargement? Si la taille de la pile est allouée de manière dynamique, comment le dépassement de pile peut-il avoir lieu (car si la taille de la pile dépasse la limite, le gestionnaire de page allouera de l'espace pour développer la pile). En cas d'attribution dynamique, comment la pile peut-elle passer de l'adresse supérieure à l'adresse inférieure (parce que l'adresse virtuelle incrémente automatiquement le stockage alloué?)

2) De plus, si la mémoire est allouée dynamiquement avec malloc, la taille de la région de données augmente ?

Merci & Cordialement,

Mousey.

Répondre

3

1) Cela dépend de l'OS, mais un ty Le schéma pical est pour le système d'exploitation de vous donner une page de mémoire virtuelle (pages sont généralement de 4 Ko) pour la pile, puis marque la page de mémoire virtuelle immédiatement après comme une «page de garde». Il s'agit d'un indicateur spécial qui provoque le déclenchement d'une exception de niveau inférieur lorsqu'une application tente d'y écrire. Le système d'exploitation gère l'exception lorsque vous tentez d'écrire dans la page de garde (ce qui se produit lorsque vous agrandissez la pile après la taille d'allocation initiale), alloue cette page pour vous (par exemple, la mappe sur une page de mémoire physique). réexécute votre programme à partir de l'instruction où l'écriture défectueuse s'est produite. Cela fonctionnera cette fois puisque la page a été sauvegardée par de la vraie mémoire. Au-delà d'un certain point (généralement 1 Mo), le système d'exploitation cesse de le faire et déclenche une exception de dépassement de pile. C'est simplement parce que ceux-ci sont généralement indicatifs d'une erreur de programme, et le code qui a vraiment besoin d'énormes piles peut allouer de la mémoire pour toutes les données de pile sur le tas.

2) Le segment de données ne "grandit" pas vraiment. Les programmes modernes ont un espace d'adressage de mémoire virtuelle fixe. malloc() utilise un schéma pour sculpter cet espace et en sauvegarder des parties avec de la vraie mémoire physique.

Je pense que vos deux questions suggèrent une meilleure compréhension de la façon dont le système d'exploitation fournit de la mémoire physique à vos programmes.Le concept clé dans les systèmes modernes est la mémoire virtuelle. Wikipedia's page on virtual memory est un bon endroit pour commencer.

Si vous voulez développer des connaissances détaillées, un manuel d'OS serait un bon point de départ. De préférence, c'est mieux que tout ce que j'avais quand j'ai suivi ce cours d'OS à l'université :)

+0

Merci beaucoup pour la réponse. Aussi, je lis un livre d'OS, il dit que malloc alloue de l'espace sur l'espace de swap, donc j'ai posé la question d'une manière différente. – mousey

+0

"malloc" ne mappe pas la mémoire physique dans votre processus, à la place, le noyau le fait une fois que vous écrivez dans la mémoire retournée par malloc. Vous pouvez expérimenter pour vous-même: même si vous malloc centaines de megs, la quantité de RAM physique utilisée n'augmentera pas. –

+0

@Dietrich Donc, il devrait être mappé à mon adresse virtuelle non? Un autre programme sage ne fonctionne pas! – mousey

0

1) L'allocation de mémoire dynamique provient du tas et non de la pile. La pile est un bloc de mémoire par thread qui gère également les variables locales et les adresses de retour pendant les appels de fonction. Le tas est juste un ou plusieurs blocs de mémoire alloués à partir du système d'exploitation, que le C RTL subdivise comme nécessaire pour satisfaire les appels malloc. En ce qui concerne la pile, elle est généralement de taille fixe car, dans un programme sans récursion infinie, vous ne devriez avoir besoin que d'une quantité finie. Si vous continuez à récurer, vous déborderez, ce qui est une bonne chose car c'est un échec net. Quant à grandir en mémoire, c'est un détail d'implémentation des processeurs.

2) Pas nécessairement. Tant que l'allocation de mémoire actuelle de l'OS est suffisante, malloc l'utilise. Une fois que cela est parti, cela peut entraîner une allocation supplémentaire.

Je sais que vous voulez plus de détails ici, mais je ne suis pas sûr de ce qui est utile. Je pourrais parler de la façon dont le tas est généralement implémenté comme des listes chaînées de blocs libres avec des en-têtes d'arènes qui définissent leur taille, ou comment certains systèmes utilisent des blocs de taille fixe pour limiter les fragmentations, ou même comment les bulles de mémoire sont fusionnées. un bloc suffisamment grand est trouvé. Cependant, tous ces détails de mise en œuvre peuvent s'avérer ne pas s'appliquer dans votre cas, du moins pas exactement.

+0

1) Je ne parle pas de l'allocation de mémoire dynamique C! La question est de savoir comment les piles sont allouées par le noyau. Comment le noyau sait-il la taille de la pile! 2) Pouvez-vous expliquer plus en détail les pls. – mousey

+0

1) La manière habituelle consiste à assigner à un thread un bloc de mémoire fixe à utiliser comme pile. –

+0

Pour chaque thread, la taille de la pile est la même? C'est un gaspillage d'espace non? – mousey

1

Stack tailles

Typiquement, chaque fil a une pile fixe lorsque le fil est créé. Exécutez ulimit -a pour voir la taille de la pile par défaut pour votre système. Sur mon système, c'est 8 MiB. Lorsque vous créez de nouveaux threads, vous pouvez leur attribuer des piles plus petites ou plus grandes (voir pthread_attr_setstacksize). Lorsque la pile croît au-delà de 8 Mio, le programme écrira dans un emplacement mémoire invalide et tombera en panne. Le noyau s'assure que les emplacements de mémoire à côté de la pile sont tous invalides, pour s'assurer que les programmes se bloquent lorsque leurs piles débordent.

Vous pouvez penser qu'une taille fixe est une perte, mais 8 MiB est la mémoire virtuelle et non mémoire physique. La différence est importante, voir ci-dessous.

Malloc

Sur les systèmes Unix, l'allocation de mémoire a deux couches à elle. La couche d'espace utilisateur est malloc (et calloc, realloc, free).Cela fait partie de la bibliothèque C, et peut être remplacé par votre propre code - Firefox le fait, et de nombreux langages de programmation utilisent leur propre schéma d'allocation autre que malloc. Diverses implémentations malloc sont multi-plateforme. La couche inférieure est mmap et sbrk. La fonction mmap est un appel système qui modifie l'espace d'adressage de votre programme. Une des choses qu'il peut faire est d'ajouter de nouvelles pages privées et anonymes dans la mémoire de votre programme.

Le but de malloc est d'obtenir de gros morceaux de mémoire virtuelle du noyau en utilisant mmap (ou sbrk) et de les répartir efficacement pour votre programme. L'appel système mmap ne fonctionne que par multiples de 4 KiB (sur la plupart des systèmes).

Mémoire: virtuel par rapport réel

Rappelez-vous que la pile et l'ensemble de la mémoire retournée par mmap est juste la mémoire virtuelle, pas RAM physique. Le noyau n'alloue pas de RAM physique à votre processus tant que vous ne l'utilisez pas réellement.

Lorsque vous obtenez une mémoire anonyme du noyau, soit sur le tas ou la pile, elle est remplie de zéros. Au lieu de vous donner des centaines de pages de RAM physique pré-remplie avec des zéros, cependant, le noyau fait que toute cette mémoire virtuelle partage une seule page de RAM physique. La mémoire virtuelle est marquée en lecture seule. Dès que vous y écrivez, le processeur lève une exception, transfère le contrôle au noyau et le noyau alloue une nouvelle page, inscriptible, mise à zéro pour votre programme.

Ceci explique pourquoi:

  • calloc est plus rapide que malloc + memset (car calloc sait que les mmap « pages d sont pré-mise à zéro et memset force l'allocation de mémoire vive)
  • Vous pouvez allouer beaucoup plus de mémoire que combiné RAM + swap (car il n'est pas utilisé jusqu'à ce que vous écrivez à lui)
+0

@Dietrich Merci beaucoup pour la réponse .so chaque fois que malloc utilise sbrk ou mmap la mémoire est attachée à quelle région? (Données, pile ou texte). Ce devrait être des données, n'est-ce pas? – mousey

+0

Intéressant, mais une grande partie de cela ne s'applique qu'à Unix. –

+0

@Steven Windows ne différencie pas entre les régions? Généralement, c'est fait dans l'exécutable (PE dans Windows). Ainsi, le système peut imposer des restrictions (ex: marquage du texte ou du code en lecture seule ou si le système dépasse une région particulière, il donne une exception) – mousey