Dans le diagramme que vous avez posté, la "rupture" - l'adresse manipulée par brk
y sbrk
-est la ligne pointillée en haut du tas.
La documentation que vous avez lue décrit cela comme la fin du "segment de données" parce que dans les systèmes traditionnels (pré-bibliothèques partagées, pré-bibliothèques en ligne, etc. mmap
) Unix, le segment de données était continu avec le tas ; avant le démarrage du programme, le noyau chargeait les blocs "texte" et "données" dans la RAM en commençant à l'adresse zéro (en fait, un peu au-dessus de l'adresse zéro, de sorte que le pointeur NULL ne pointe véritablement sur rien) et plaçait l'adresse de rupture à la fin du segment de données. Le premier appel à malloc
utiliserait alors sbrk
pour déplacer la rupture et créer le tas entre les deux le haut du segment de données et la nouvelle adresse de rupture, plus élevée, comme indiqué dans le schéma, et l'utilisation ultérieure de la fonction malloc
l'utiliserait pour agrandir le tas si nécessaire.
Pendant ce temps, la pile commence au sommet de la mémoire et se développe vers le bas. La pile n'a pas besoin d'appels système explicites pour s'agrandir ; soit elle commence avec autant de RAM allouée qu'elle ne pourra jamais en avoir (c'est l'approche traditionnelle), soit il existe une région d'adresses réservées sous la pile, à laquelle le noyau alloue automatiquement de la RAM lorsqu'il remarque une tentative d'écriture à cet endroit (c'est l'approche moderne). Dans tous les cas, il peut y avoir ou non une région "de garde" au bas de l'espace d'adressage qui peut être utilisée pour la pile. Si cette région existe (c'est le cas de tous les systèmes modernes), elle est désaffectée de façon permanente. soit la pile ou le tas tente de s'agrandir, vous obtenez une erreur de segmentation. Traditionnellement, cependant, le noyau n'essayait pas de faire respecter une frontière ; la pile pouvait grandir dans le tas, ou le tas pouvait grandir dans la pile, et dans tous les cas, ils gribouillaient sur les données de l'autre et le programme plantait. Si vous étiez très chanceux, il se plantait immédiatement.
Je ne sais pas d'où vient le chiffre 512GB dans ce diagramme. Il implique un espace d'adressage virtuel de 64 bits, ce qui est incompatible avec la carte mémoire très simple que vous avez là. Un véritable espace d'adressage de 64 bits ressemble davantage à ceci :
Legend: t: text, d: data, b: BSS
Ce n'est pas du tout à l'échelle, et il ne faut pas l'interpréter comme la manière exacte dont un système d'exploitation donné fait les choses (après l'avoir dessiné, j'ai découvert que Linux place en fait l'exécutable beaucoup plus près de l'adresse zéro que je ne le pensais, et les bibliothèques partagées à des adresses étonnamment élevées). Les régions noires de ce diagramme ne sont pas mappées -- tout accès provoque un défaut de segmentation immédiat -- et sont les suivantes gigantesque par rapport aux zones grises. Les régions gris clair sont le programme et ses bibliothèques partagées (il peut y avoir des douzaines de bibliothèques partagées) ; chacune d'entre elles a un nom de fichier indépendant le segment de texte et de données (et le segment "bss", qui contient également des données globales mais qui est initialisé à tous les bits zéro plutôt que de prendre de la place dans l'exécutable ou la bibliothèque sur le disque). Le tas n'est plus nécessairement continu avec le segment de données de l'exécutable -- je l'ai dessiné de cette façon, mais il semble que Linux, au moins, ne le fasse pas. La pile n'est plus fixée au sommet de l'espace d'adressage virtuel, et la distance entre le tas et la pile est si énorme que vous n'avez pas à vous soucier de la traverser.
La rupture est toujours la limite supérieure du tas. Cependant, ce que je n'ai pas montré, c'est qu'il pourrait y avoir des douzaines d'allocations indépendantes de mémoire quelque part dans le noir, effectuées avec mmap
au lieu de brk
. (L'OS s'efforcera de les garder loin de la brk
pour qu'ils n'entrent pas en collision).
1 votes
Que faites-vous quand vous n'avez plus d'espace ? Vous changez pour un disque dur. Lorsque vous avez utilisé l'espace, vous le libérez pour d'autres types d'informations.
36 votes
@Igoris : Vous confondez mémoire physique (que vous pouvez échanger sur le disque si nécessaire, en utilisant la mémoire virtuelle) et espace adresse . Lorsque vous remplissez votre espace d'adressage, aucun échange ne vous permettra de récupérer les adresses du milieu.
10 votes
Pour rappel, le
brk()
L'appel système est plus utile en langage assembleur qu'en C. En C,malloc()
doit être utilisé à la place debrk()
à des fins d'allocation de données - mais cela n'invalide en rien la question proposée.0 votes
Les gens doivent arrêter de parler de le site pile, s'il vous plaît. Nous vivons dans un monde multithread !
0 votes
@Ben Les piles de threads enfants ne sont-elles pas allouées sur le tas ? Est-ce seulement pour les pthreads ?
2 votes
@Brian : Le tas est une structure de données complexe permettant de gérer des régions de tailles et d'alignements différents, le pool libre, etc. Les piles de threads sont toujours des séquences contiguës (dans l'espace d'adressage virtuel) de pages complètes. Dans la plupart des systèmes d'exploitation, il y a un allocateur de pages qui sous-tend les piles, le tas et les fichiers mappés en mémoire.
0 votes
@Ben Mais il n'y a qu'une seule "pile" en S majuscule qui est manipulée par brk() et sbrk(), n'est-ce pas ? Les autres piles de threads sont des choses moins importantes manipulées par le code utilisateur, correct ?
2 votes
@Brian : Qui a dit qu'il n'y avait aucun "Stack" manipulé par
brk()
ysbrk()
? Les piles sont gérées par l'allocateur de pages, à un niveau beaucoup plus bas.0 votes
@Ben Oh, quand je suis revenu sur cette question, je pensais qu'il y avait une pile manipulée par ces appels système, mais maintenant je me souviens qu'il s'agit en fait du sommet du tas. Je pensais qu'il devait y avoir une pile canonique, mais ce que vous dites a du sens maintenant. Ce qui se passe dans les adresses de la pile n'a pas d'importance (tant que vous avez un pointeur de pile). quelque part ou autre) parce que vous n'êtes pas censé les partager entre les fils de toute façon.