Comment la taille de la pile et du tas est-elle limitée par le système d'exploitation?

21

Remarque : si vous devez considérer un système d'exploitation spécifique pour pouvoir répondre, veuillez considérer Linux.

Chaque fois que j'exécute un programme, un espace mémoire virtuel lui sera attribué, avec une zone pour sa pile et une pour son tas.

Question 1 : la pile et le tas ont-ils une limite de taille statique (par exemple, 2 gigaoctets chacun), ou cette limite est-elle dynamique, changeant en fonction des allocations de mémoire pendant l'exécution du programme (c'est-à-dire, 4 gigaoctets au total à utiliser par les deux, donc si un programme n'utilise que la pile, il pourra avoir une pile de 4 gigaoctets)?

Question 2 : Comment la limite est-elle définie? S'agit-il de la mémoire RAM totale disponible?

Question 3 : Qu'en est-il des sections de texte (code) et de données, comment sont-elles limitées?

Daniel Scocco
la source
Stack: unix.stackexchange.com/questions/145557/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Réponses:

23

Il existe deux limites de mémoire différentes. La limite de mémoire virtuelle et la limite de mémoire physique.

Mémoire virtuelle

La mémoire virtuelle est limitée par la taille et la disposition de l'espace d'adressage disponible. Habituellement, au tout début se trouve le code exécutable et les données statiques et le passé qui font croître le tas, tandis qu'à la fin, la zone est réservée par le noyau, avant les bibliothèques partagées et la pile (qui, sur la plupart des plates-formes, croît). Cela donne un espace libre au tas et à la pile pour grandir, les autres zones étant connues au démarrage du processus et corrigées.

La mémoire virtuelle libre n'est pas initialement marquée comme utilisable, mais est marquée comme telle lors de l'allocation. Bien que le tas puisse atteindre toute la mémoire disponible, la plupart des systèmes n'augmentent pas automatiquement les piles. La limite par défaut de l'IIRC pour la pile est de 8 Mo sous Linux et de 1 Mo sous Windows et peut être modifiée sur les deux systèmes. La mémoire virtuelle contient également des fichiers et du matériel mappés en mémoire.

L'une des raisons pour lesquelles la pile ne peut pas être développée automatiquement (arbitrairement) est que les programmes multithread ont besoin d'une pile distincte pour chaque thread, afin qu'ils finissent par se gêner mutuellement.

Sur les plates-formes 32 bits, la quantité totale de mémoire virtuelle est de 4 Go, Linux et Windows réservant normalement le dernier 1 Go pour le noyau, vous offrant au maximum 3 Go d'espace d'adressage. Il existe une version spéciale de Linux qui ne réserve rien pour vous donner une 4GiB complète. Il est utile pour les rares cas de grandes bases de données où le dernier 1 Go enregistre la journée, mais pour une utilisation régulière, il est légèrement plus lent en raison des rechargements de table de pages supplémentaires.

Sur les plates-formes 64 bits, la mémoire virtuelle est 64EiB et vous n'avez pas à y penser.

Mémoire physique

La mémoire physique n'est généralement allouée par le système d'exploitation que lorsque le processus doit y accéder. La quantité de mémoire physique utilisée par un processus est un nombre très flou, car une partie de la mémoire est partagée entre les processus (le code, les bibliothèques partagées et tout autre fichier mappé), les données des fichiers sont chargées en mémoire à la demande et supprimées en cas de manque de mémoire et La mémoire "anonyme" (celle qui n'est pas sauvegardée par des fichiers) peut être permutée.

Sous Linux, ce qui se produit lorsque vous manquez de mémoire physique dépend du vm.overcommit_memoryparamètre système. La valeur par défaut est de sur-engager. Lorsque vous demandez au système d'allouer de la mémoire, il vous en donne, mais alloue uniquement la mémoire virtuelle. Lorsque vous accédez réellement à la mémoire, il essaie d'obtenir de la mémoire physique à utiliser, en supprimant les données qui peuvent être relues ou en échangeant des éléments si nécessaire. S'il trouve qu'il ne peut rien libérer, il supprimera simplement le processus de l'existence (il n'y a aucun moyen de réagir, car cette réaction pourrait nécessiter plus de mémoire et cela conduirait à une boucle sans fin).

C'est ainsi que les processus meurent sur Android (qui est aussi Linux). La logique a été améliorée avec la logique qui traite de supprimer de l' existence en fonction de ce processus fait et quel âge il est. Les processus Android cessent simplement de faire quoi que ce soit, mais restent en arrière-plan et le "tueur de mémoire" les tuera lorsqu'il aura besoin de mémoire pour de nouveaux.

Jan Hudec
la source
9

Je pense qu'il est plus facile de répondre à cette question par l'ordre d'utilisation de la mémoire.

Question 3: Qu'en est-il des sections de texte (code) et de données, comment sont-elles limitées? Le texte et les données sont préparés par le compilateur. L'exigence pour le compilateur est de s'assurer qu'ils sont accessibles et de les emballer dans la partie inférieure de l'espace d'adressage. L'espace d'adressage accessible sera limité par le matériel, par exemple si le registre de pointeur d'instruction est de 32 bits, alors l'espace d'adressage de texte serait de 4 Gio.

Question 2: Comment la limite est-elle définie? S'agit-il de la mémoire RAM totale disponible? Après le texte et les données, la zone au-dessus est le tas. Avec la mémoire virtuelle, le tas peut pratiquement se développer jusqu'à près de l'espace d'adressage max.

Question 1: la pile et le tas ont-ils une limite de taille statique (par exemple, 2 gigaoctets chacun), ou cette limite est-elle dynamique, changeant en fonction des allocations de mémoire pendant l'exécution du programme (c'est-à-dire 4 gigaoctets au total à utiliser par les deux, donc si un programme n'utilise que la pile, il pourra avoir une pile de 4 gigaoctets)? Le dernier segment de l'espace d'adressage du processus est la pile. La pile prend le segment d'extrémité de l'espace d'adressage et il commence à partir de l'extrémité et pousse vers le bas .

Parce que le tas grandit et la pile grandit, ils se limitent essentiellement. De plus, comme les deux types de segments sont accessibles en écriture, ce n'était pas toujours une violation pour l'un d'entre eux de traverser la frontière, vous pourriez donc avoir un tampon ou un débordement de pile. Il existe maintenant un mécanisme pour les empêcher de se produire.

Il existe une limite définie pour le tas (pile) pour chaque processus au départ. Cette limite peut être modifiée au moment de l'exécution (à l'aide de brk () / sbrk ()). Fondamentalement, ce qui se passe, c'est lorsque le processus a besoin de plus d'espace mémoire et qu'il n'a plus d'espace alloué, la bibliothèque standard émet l'appel vers le système d'exploitation. Le système d'exploitation allouera une page, qui sera généralement gérée par la bibliothèque utilisateur pour le programme à utiliser. Autrement dit, si le programme veut 1 Ko, le système d'exploitation donnera 4 Ko supplémentaires et la bibliothèque donnera 1 Ko au programme et il lui restera 3 Ko à utiliser lorsque le programme en demandera plus la prochaine fois.

La plupart du temps, la mise en page sera du texte, des données, du tas (grandit), de l'espace non alloué et enfin de la pile (grandit). Ils partagent tous le même espace d'adressage.

imel96
la source