2014-10-09 12 views
7

Ich untersuche das Speicherlayout eines bestimmten Prozesses. Ich stelle fest, dass der Startspeicherplatz für jeden Prozess nicht 0 ist. Auf dieser website beginnt TEXT bei 0x08048000. Ein Grund kann sein, die Adresse mit dem NULL-Zeiger zu unterscheiden. Ich frage mich nur, ob es noch einen anderen guten Grund gibt? Vielen Dank.Speicher Startort in C

+0

Warum ist 0x00400000 der Standard-Basisadresse für eine ausführbare Datei? http://blogs.msdn.com/b/oldnewthing/archive/2014/10/03/10562176.aspx – auselen

Antwort

0

A loader Lasten in einem binären Segmenten in dem Speicher: Text (Konstanten), Daten-Code. Es ist nicht notwendig, von 0 zu starten, und wie C ist das Problem von Bugs rund um Null, wie in a[i], die sogar gefährlich ist. Dies erlaubt (auf einigen Prozessoren), Segmentierungsfehler abzufangen.

Es wäre die C-Laufzeit, die einen linearen Adressraum von 0 einführt. Das wäre vorstellbar, wenn C die Implementierungssprache des Betriebssystems ist. Aber dient keinem Zweck; Der Heapspeicher beginnt bei 0. Das Speichermodell ist eines der Segmente. Ein Code-Segment ist möglicherweise vor Änderungen durch einige Prozessoren geschützt.

Und in Segmenten Zuweisung geschieht in C Runtime verwaltete Speicherblöcke.

Ich könnte hinzufügen, dass physische 0 und höher oft vom Betriebssystem selbst verwendet wird.

2

Ich denke, das bringt es auf:

Jeder Prozess seinen eigenen Satz von Seitentabellen hat, aber es gibt einen Haken. Sobald virtuelle Adressen aktiviert sind, gelten sie für alle Software, die auf der Maschine ausgeführt wird, einschließlich des Kernels selbst. Daher muss ein Teil des virtuellen Adressraums für den Kernel reserviert sein.

Also während der Prozess seinen eigenen Adressraum bekommt. Ohne dem Kernel einen Block zuzuordnen, wäre es nicht in der Lage, Kernel-Code und Daten zu adressieren.

Dies ist immer der erste Speicherblock, der angezeigt wird, und enthält daher die Adresse 0. Der Benutzermodusbereich beginnt darüber hinaus, und daher befinden sich sowohl der Stapel als auch der Heapspeicher dort.

von NULL Zeiger Erkennungsmerkmal

Selbst wenn der Benutzer-Modus Raum an der Adresse gestartet 0, gäbe es keine Daten an die Adresse zugewiesen sein 0 wie in dem Stapel sein wird oder der Haufen, die sich nicht Beginnen Sie am Anfang des Benutzerbereichs. Daher könnte NULL (mit dem Wert 0) noch verwendet werden und ist kein Grund für dieses Layout.

Ein Vorteil im Zusammenhang mit der NULL und der erste Block als Kernel-Speicher ist jeder Versuch, NULL zu lesen/zu schreiben, löst einen Segmentierungsfehler aus.

+0

Dennoch, was genau liegt in der '0 .. 0x08048000' Bereich? –

3

Der Null-Zeiger muss nicht wirklich 0 sein. Im C-Standard ist garantiert, dass ein 0-Wert im Kontext eines Zeigers vom Compiler als NULL behandelt wird.

Aber die 0, die Sie in Ihrem Quellcode verwenden, ist nur syntaktischen Zucker, die keine Beziehung zu der tatsächlichen physischen Adresse der Null-Zeiger-Wert hat "zeigt" auf.siehe

Für weitere Informationen:

Eine Anwendung auf Ihrem Betriebssystem hat seinen einzigartigen Adressraum, der es als ein kontinuierlicher Speicherblock sieht (die Speicher ist nicht physisch kontinuierlich, es ist nur "der Eindruck", den das Betriebssystem jedem Programm gibt.

Für den größten Teil, jeden virtuelle Speicherraum des Prozesses wird auf ähnliche und vorhersehbare Weise angelegt (dies ist das Speicherlayout in einem Linux-Prozess, ein 32-Bit-Modus):

Memory layout in a Linux process (Bild von Anatomy of a Program in Memory)

Sehen Sie sich das Textsegment an (die Standardtextbasis auf x86 ist 0x08048000, die vom Standardlinkerskript für die statische Bindung ausgewählt wurde).

Warum die magische 0x08048000? Wahrscheinlich weil Linux diese Adresse vom System V i386 ABI ausgeliehen hat.

... und warum hat dann System V 0x08048000 verwendet?

Der Wert wurde ausgewählt, um den Stapel unter dem .text-Abschnitt aufzunehmen, , der nach unten wächst. Die 0x48000 Bytes könnten durch die gleiche Seite Tabelle zugeordnet werden, die bereits vom Abschnitt .text benötigt wird (wodurch in den meisten Fällen eine Seitentabelle gespeichert wird), während die verbleibenden 0x08000000 mehr Raum für stapelhungrige Anwendungen zulassen würden.

Gibt es etwas unter 0x08048000? Es könnte nichts sein (es ist nur 128M), aber you can pretty much map anything you desire there, using the mmap() system call. auch

Siehe: