Ein Prozeß im Speicher

Beim Starten eines Prozesses wird von einem Teil des Betriebssystems, dem Lader, eine ausführbare Programmdatei gelesen, und großteils in einen freien Speicherbereich kopiert. Bei einfachen Betriebssystemen wie CP/M oder MSDOS und Windows gibt es einen Speicherbereich, in dem alle gerade laufenden Prozesse zu finden sind; dann können die einzelnen Prozesse versehentlich oder absichtlich sich gegenseitig oder womöglich das Betriebssystem beeinflussen. Unter Betriebssystemen mit einer virtuellen Speicherverwaltung (DEC-VMS, Unix, Windows NT) sieht jeder Prozeß nur einen ihm zugewiesenen Speicher, und das Betriebssystem kann darauf achten, daß nicht illegalerweise anderer Speicher verwendet wird als der vom Betriebssystem für diesen Prozeß vorgesehene (sie dazu auch Betriebssysteme).

Die zu kopierenden Bereiche sind üblicherweise in verschiedene Segmente7.5unterteilt. Dies kommt daher, daß der Compiler, Assembler und Linker (siehe Programmerstellung) ihre jeweiligen Eingabedateien sequentiell durchlaufen, und dabei aber verschiedenartige Informationen sammeln: ausführbarer Maschinencode fällt vermischt mit anzulegenden Variablen oder Konstanten an. Deshalb werden jeweils vom Typ her ähnliche Informationen in Segmenten gesammelt: eines für Maschinencode, eines für Konstanten et cetera.

So brauchen der Compiler und der Assembler nur bei jedem Teil ihrer Ausgabe vermerken, zu welchem Segment es zugeschlagen werden soll. Erst der Linker sortiert die zusammengehörigen Teilstücke dann in den Segmenten ein. Ein Beispiel dafür ist die Anweisung .text im Assemblerlisting in Vom C-Programm zum Prozeß. Sie weist den Linker an, alles danach folgende (bis zu einer anderen Segmentdirektive, .data beispielsweise) in das .text-Segment zu packen. Weil in diesem Beispielprogramm keine globalen und konstanten Daten verwendet werden, und alles im .text-Segment landet, ist dies die einzige Segmentanweisung.

Es gibt praktisch immer ein Segment, in dem Maschinencode zu finden ist. Dieses heißt manchmal TEXT, .text, .CODE oder so ähnlich.

Ein weiteres Segment besteht aus den globalen Variablen eines Programms, die bei Programmstart initialisiert sein müssen. Dieses Segment kann DATA, .data oder so ähnlich heißen.

Globale Variablen, die keinen bestimmten Anfangswert bei Programmstart benötigen, brauchen auch nicht in voller Länge in der Programmdatei abgelegt zu werden; es reicht wenn die Länge des dafür nötigen Bereichs in der Datei vermerkt ist. Ein solches Segment heißt block storage segment, BSS, oder .bss. Erst beim Erzeugen eines Prozesses muß dieser Bereich im Speicher angelegt werden.

Je nach Fähigkeiten des Betriebssystems kann es auch noch feinere Unterteilungen geben; beispielsweise könnten für globale Daten zwei verschiedene Segmente verwendet werden: eines für solche, die während der Laufzeit konstant sind, und eines für die restlichen, die sich ändern dürfen. In diesem Fall kann das Betriebssystem einen versehentlichen schreibenden Zugriff auf Konstanten unterbinden7.6.

Anmerkung: lokale, automatische Vairbalen werden nicht in einem besonderen Segment im ausführbaren Programm abgelegt, sondern entstehen erst zur Laufzeit auf dem Stack; siehe Der Programmstack.

Neben den Bereichen der Programmdatei, die zum Start in den Speicher kopiert werden müssen, enthält die Programmdatei je nach Betriebssystem noch Informationen für den Lader, beispielsweise wie groß die einzelnen Segmente sind, wieviel Stackspeicher (siehe Der Programmstack) benötigt wird, gegebenenfalls Informationen über besondere Zugriffsrechte, oder ähnliches.

TODO:

Verwaltung freier Speicher manuell (malloc()/free() beziehungsweise new/delete) oder automatisch (Java, LISP, garbage collection)

statischer Speicher und globale Variablen, Konstanten, lokale/automatische/globale/statische Variablen, Adressen, Zeiger

AnyWare@Wachtler.de