Wie ist die Größe des Stapels und des Heaps durch das Betriebssystem begrenzt?


21

Hinweis : Wenn Sie ein bestimmtes Betriebssystem in Betracht ziehen müssen, um antworten zu können, ziehen Sie bitte Linux in Betracht.

Jedes Mal, wenn ich ein Programm ausführe, wird ihm ein virtueller Speicherbereich mit einem Bereich für den Stapel und einem für den Heap zugewiesen.

Frage 1 : Haben der Stack und der Heap eine statische Größenbeschränkung (z. B. jeweils 2 Gigabyte) oder ist diese Begrenzung dynamisch und ändert sich entsprechend der Speicherzuweisungen während der Ausführung des Programms (dh insgesamt 4 Gigabyte, die von verwendet werden sollen) beide, wenn also ein Programm nur den Stack verwendet, kann es einen Stack mit 4 Gigabyte haben?

Frage 2 : Wie ist das Limit definiert? Ist es der insgesamt verfügbare RAM-Speicher?

Frage 3 : Was ist mit den Text- (Code-) und Datenabschnitten, wie sind sie begrenzt?


Antworten:


23

Es gibt zwei verschiedene Speichergrenzen. Das virtuelle Speicherlimit und das physische Speicherlimit.

Virtueller Speicher

Der virtuelle Speicher ist durch die Größe und das Layout des verfügbaren Adressraums begrenzt. Ganz am Anfang stehen in der Regel der ausführbare Code und die statischen Daten sowie die Vergangenheit, die den Heap vergrößern, während am Ende der vom Kernel reservierte Bereich vor den gemeinsam genutzten Bibliotheken und dem Stack (der auf den meisten Plattformen kleiner wird) angezeigt wird. Dies gibt Heap- und Stack-freiem Speicherplatz zum Wachsen. Die anderen Bereiche sind beim Start des Prozesses bekannt und wurden behoben.

Der freie virtuelle Speicher wird anfangs nicht als nutzbar markiert, sondern bei der Zuweisung als nutzbar markiert. Während der Heap-Speicher auf den gesamten verfügbaren Arbeitsspeicher anwachsen kann, werden Stapel auf den meisten Systemen nicht automatisch vergrößert. Das IIRC-Standardlimit für den Stapel beträgt 8 MB unter Linux und 1 MB unter Windows und kann auf beiden Systemen geändert werden. Der virtuelle Speicher enthält auch alle Speicherzuordnungsdateien und -hardware.

Ein Grund, warum Stapel nicht automatisch (willkürlich) aufgebaut werden können, ist, dass Multithread-Programme für jeden Thread einen separaten Stapel benötigen, damit sie sich gegenseitig im Weg stehen.

Auf 32-Bit-Plattformen beträgt der gesamte virtuelle Speicher 4 GB, wobei Linux und Windows normalerweise die letzten 1 GB für den Kernel reservieren, sodass Sie höchstens 3 GB Adressraum haben. Es gibt eine spezielle Linux-Version, die nichts reserviert, was Ihnen volle 4GiB bietet. Dies ist nützlich für den seltenen Fall großer Datenbanken, in denen das letzte 1GiB den Tag speichert. Bei regelmäßiger Verwendung ist es jedoch etwas langsamer, da zusätzliche Seitentabellen neu geladen werden.

Auf 64-Bit-Plattformen beträgt der virtuelle Speicher 64EiB, und Sie müssen nicht darüber nachdenken.

Physikalischer Speicher

Der physische Speicher wird normalerweise nur vom Betriebssystem zugewiesen, wenn der Prozess darauf zugreifen muss. Wie viel physischen Speicher ein Prozess verwendet, ist eine sehr unscharfe Zahl, da ein Teil des Arbeitsspeichers von Prozessen gemeinsam genutzt wird (der Code, gemeinsam genutzte Bibliotheken und andere zugeordnete Dateien). Daten aus Dateien werden bei Bedarf in den Arbeitsspeicher geladen und verworfen, wenn nicht genügend Arbeitsspeicher vorhanden ist Möglicherweise wird der "anonyme" Speicher (der Speicher, der nicht durch Dateien gesichert ist) ausgetauscht.

Was unter Linux passiert, wenn der physische Speicher voll ist, hängt von der vm.overcommit_memorySystemeinstellung ab. Standardmäßig wird ein Overcommit durchgeführt. Wenn Sie das System auffordern, Speicher zuzuweisen, werden Ihnen einige zugewiesen, jedoch nur der virtuelle Speicher. Wenn Sie tatsächlich auf den Speicher zugreifen, wird versucht, physischen Speicher zu verwenden. Dabei werden Daten verworfen, die neu gelesen oder bei Bedarf ausgetauscht werden können. Wenn es feststellt, dass es nichts freisetzen kann, wird es einfach den Prozess aus der Existenz entfernen (es gibt keine Möglichkeit zu reagieren, da diese Reaktion mehr Speicher erfordern könnte und dies zu einer Endlosschleife führen würde).

So sterben Prozesse auf Android (das ist auch Linux). Die Logik wurde durch die Logik verbessert, welcher Prozess aus der Existenz entfernt werden soll, basierend darauf, was der Prozess tut und wie alt er ist. Dann hören Android-Prozesse einfach auf, etwas zu tun, sitzen aber im Hintergrund und der "Out-of-Memory-Killer" wird sie töten, wenn Speicher für neue benötigt wird.


9

Ich denke, es ist einfacher, dies in der Reihenfolge der Verwendung des Speichers zu beantworten.

Frage 3: Was ist mit den Text- (Code-) und Datenabschnitten, wie sind sie begrenzt? Text und Daten werden vom Compiler aufbereitet. Der Compiler muss sicherstellen, dass auf sie zugegriffen werden kann, und sie müssen im unteren Teil des Adressraums gepackt werden. Der zugreifbare Adressraum wird durch die Hardware begrenzt. Wenn z. B. das Befehlszeigerregister 32-Bit ist, beträgt der Textadressraum 4 GB.

Frage 2: Wie ist das Limit definiert? Ist es der insgesamt verfügbare RAM-Speicher? Nach Text und Daten ist der Bereich darüber der Heap. Mit virtuellem Speicher kann der Heap praktisch in der Nähe des maximalen Adressraums wachsen .

Frage 1: Haben der Stack und der Heap eine statische Größenbeschränkung (z. B. jeweils 2 Gigabyte) oder ist diese Begrenzung dynamisch und ändert sich entsprechend der Speicherzuweisungen während der Ausführung des Programms (dh insgesamt 4 Gigabyte, die von verwendet werden sollen) beide, wenn also ein Programm nur den Stack verwendet, kann es einen Stack mit 4 Gigabyte haben? Das letzte Segment im Prozessadressraum ist der Stapel. Der Stapel nimmt das Endsegment des Adressraums und beginnt am Ende und wächst nach unten .

Da der Haufen größer und der Stapel kleiner wird, begrenzen sie sich gegenseitig. Da beide Segmenttypen beschreibbar sind, war es nicht immer eine Verletzung für einen von ihnen, die Grenze zu überschreiten, sodass ein Puffer- oder Stapelüberlauf auftreten kann. Jetzt gibt es Mechanismen, um sie davon abzuhalten.

Es gibt ein festgelegtes Limit für Heap (Stack) für jeden Prozess, mit dem begonnen wird. Dieses Limit kann zur Laufzeit geändert werden (mit brk () / sbrk ()). Grundsätzlich geschieht dies, wenn der Prozess mehr Speicherplatz benötigt und nicht mehr genügend Speicherplatz zur Verfügung steht. Die Standardbibliothek ruft das Betriebssystem auf. Das Betriebssystem weist eine Seite zu, die normalerweise von der Benutzerbibliothek verwaltet wird, damit das Programm sie verwenden kann. Das heißt, wenn das Programm 1 KiB benötigt, gibt das Betriebssystem zusätzliche 4 KiB und die Bibliothek gibt dem Programm 1 KiB und es bleiben 3 KiB zur Verwendung übrig, wenn das Programm das nächste Mal nach mehr fragt.

Die meiste Zeit wird das Layout aus Text, Daten, Heap (vergrößert), nicht zugewiesenem Speicherplatz und schließlich Stack (verkleinert) bestehen. Sie teilen sich alle den gleichen Adressraum.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.