Virtuelle Speicherverwaltung


Virtuelle Speicherverwaltung
Schemabild der Anwendung des virtuellen Speichermanagement:
links: virtueller Speicherraum pro Prozess, Speicher ist linear und unfragmentiert
rechts: reale Speicherquellen, typischerweise RAM oder Festplatte, mehrere, auch kleine Speicherfragmente können verwendet werden; in rot Speicherverwendung anderer Prozesse, unsichtbar im virtuellen Speicherraum

Die virtuelle Speicherverwaltung (engl. virtual memory management) ist eine spezielle Speicherverwaltung in einem Computer. Die Übersetzung des englischen Begriffs stellt eine Hypallage dar – nicht der Verwaltungsvorgang, sondern der zu verwaltende Speicher ist virtuell. Der virtuelle Speicher bezeichnet den vom tatsächlich vorhandenen Arbeitsspeicher unabhängigen Adressraum, der einem Prozess vom Betriebssystem zur Verfügung gestellt wird.

Der virtuelle Speicher wurde 1956 von Fritz-Rudolf Güntsch entwickelt[1] und findet heute in nahezu allen modernen Betriebssystemen Verwendung.

Inhaltsverzeichnis

Motivation

Die ursprüngliche Motivation für eine Abstraktion der Speicheradressen mit virtuellen Adressen war die Vereinheitlichung der Benutzung und die mögliche Zusammenfassung verschiedener Speicherquellen. Dies wird von Güntsch in seiner Dissertation von 1957 so beschrieben:

„Der Programmierer braucht auf das Vorhandensein von Schnellspeichern keine Rücksicht zu nehmen (er braucht nicht einmal zu wissen, daß solche vorhanden sind). Denn es gibt nur eine Sorte von Adressen, mit denen programmiert werden kann, als wäre nur ein Speicher vorhanden.“

Eike Jessen: [2]

Eine weitere nützliche Eigenschaft des virtuellen Adressraums, insbesondere wenn dieser deutlich größer ist als der physikalische Speicher, ist die Möglichkeit, Speicherfragmentierungen zu kaschieren. Beispielsweise mit MS-DOS, ein OS ohne virtuelles Speichermanagement, wurde versucht, dieses Problem mit komplizierten, iterativen Speicheroptimierern (QEMM etc.) zu minimieren, jedoch nur mit begrenztem Erfolg, weswegen sich letztendlich Betriebssysteme mit virtueller Speicherverwaltung in den 1990ern für den PC durchsetzen.

Die virtuelle Speicherverwaltung ermöglicht auch die Implementierung von Speicherschutzmechanismen zur Separierung von Programmen untereinander (horizontale Trennung: Programme können im Fehlerfall nicht auf Speicher anderer Programme zugreifen) oder von Programmen vom Betriebssystem (vertikale Hierarchie), dessen Funktionieren niemals durch fehlerhafte Anwendungsprogramme gestört werden sollte.

Funktionsweise

Beziehung des Virtuellen Adressraums zum Physikalischen Adressraum für einen Prozess (32-Bit protected mode). Fragmentierter physikalischer Speicher wird dem Prozess im 2-GB-großen virtuellen Adressraum als kontinuierlich präsentiert.

Das Rechnersystem stellt jedem Prozess mit Adressen von 0 bis n-1 einen scheinbar zusammenhängenden lokalen Speicherbereich zur Verfügung, wobei n die Größe dieses Speicherbereichs ist. In Wirklichkeit besteht dieser Speicherbereich aus einzelnen Seiten definierter Größe („Pages“, veraltet auch „Kacheln“) innerhalb des virtuellen Adressraums der Maschine. Diese virtuellen Pages werden wiederum auf physische Pages abgebildet, die irgendwo im physischen Speicher oder sogar in einer Auslagerungsdatei liegen. Beim Zugriff eines Prozesses auf eine lokale Speicheradresse ersetzt das Betriebssystem diese durch eine virtuelle, welche von der Memory Management Unit des Systems in die aktuelle physische Adresse umgesetzt wird.

Eine Seitentabelle ist eine Tabelle, welche der Transformation von virtuellen in physische Seitenrahmen dient. Die optimale Seitengröße ist ein Kompromiss zwischen Häufigkeit von Seitenwechsel und Größe der Tabelle.

Eine virtuelle Adresse beschreibt also einen Ort im Speicher eines Computersystems, dessen Betriebssystem eine virtuelle Speicherverwaltung zur Adressierung verwendet. Die Gesamtheit aller virtuellen Adressen wird auch als virtueller Adressraum bezeichnet.

Nur die Betriebssysteme, die eine virtuelle Speicherverwaltung verwenden, können einen virtuellen Adressraum generieren und dadurch Speicherseiten, die physisch nicht zusammenhängend sind, für den Programmierer bzw. das Programm als logisch zusammenhängenden Speicherbereich abbilden.

Platzierungsstrategien von Betriebssystemen

Fordert ein Programm Speicher vom Betriebssystem an, besitzt das Betriebssystem Freiheiten, wo im virtuellen Speicherraum des Prozesses er dem Programm den angeforderten Speicher zuweist. Mit geschickten Platzierungsstrategien kann eine kontinuierliche Fragmentierung des virtuellen Adressraums reduziert werden, was sowohl bei einer hohen Anzahl von Speicheranforderungen und -freigaben als auch wenn der virtuelle Adressraum schon sehr voll ist um so relevanter wird.

Strategien zur Wahl geeigneter Adressen sind:

  • FirstFit: erste ausreichende Lücke
  • BestFit: kleinste ausreichende Lücke
  • NextFit: nächster freier Speicher; startet an der Stelle, an der die letzten Daten eingefügt wurden (ringförmiges Durchsuchen)
  • WorstFit: größte ausreichende Lücke; Restlücke wird zusammengelegt

Paging

Virtuelle Speichersegmente des Intel 80286.
Paging des Intel 80386, mit einer Page-Seitengröße von 4 KB.

Der Begriff Paging bezeichnet im engeren Sinn lediglich den Vorgang der Abbildung der virtuellen Adressen auf die physischen. Im weiteren (fehlerhaften) Sinne wird er synonym für Swapping benutzt.

Swapping

Swapping ist die Auslagerung eines realen RAM-Speicherbereichs in einen anderen, sekundären Speicher, typischerweise in eine Auslagerungsdatei auf eine Festplatte durch das Betriebssystem. Die Idee dahinter ist, dass bei typischen Computern die Festplatte deutlich größer ist als der verfügbare elektronische Speicher (RAM). Dieser Speicher kann ebenfalls verwendet werden, um Speicheranfragen von Programmen zu bedienen. Speicheranfragen von Programmen, die über den verfügbaren RAM hinausgehen, werden dann über Speicher aus dem Swap-Speicher bis zur maximalen virtuellen Speichergröße pro Prozess bedient. Nachteil ist, dass der auf Festplatten ausgelagerte Speicher deutlich langsamer zugreifbar ist als RAM. Jedoch ermöglicht dieses Vorgehen das Funktionieren des Programms. Um dieses Problem zu mildern versuchen Betriebssysteme mit einem Prozessmonitoring den RAM- und Swap-Speicher optimal auf die verschiedenen Prozesse zu verteilen. Länger inaktive Prozesse, also Speicherbereiche, auf die weder lesend noch schreibend zugegriffen wird, werden in den langsamen Swap-Speicher ausgelagert. Prozesse, die viele Interaktionen mit ihrem Speicher haben werden versucht, im RAM zu halten.

Dies funktioniert konkret, dass ab einem gewissen Füllgrad des RAMs besondere Prozesse („Page stealer“) beginnen, länger nicht benutzte Seiten auszulagern, um zusätzlichen physischen Platz zu gewinnen, damit das System auf eine entsprechende Anforderung schnell reagieren kann. Dieser Vorgang ist asynchron zu den Anwendungen und belastet das System nicht sonderlich. Trotzdem ist die Zugriffsgeschwindigkeit der Festplatte relevant und eine Belastung des Systems relativ anzusehen. Weiter unten sind die wichtigsten Seitenersetzungsstrategien aufgelistet. Üblicherweise wird eine Kombination aus mehreren Verfahren angewandt: Zuerst ungelesene, dann unveränderte, dann länger nicht veränderte Seiten auslagern. Soweit eine noch aktuelle Kopie einer Seite in der Auslagerungsdatei existiert, kann diese Seite ohne Weiteres zum Überschreiben freigegeben werden.

Ein Seitenfehler (engl.: page fault) tritt auf, wenn ein Programm auf eine Seite zugreift, die sich gerade nicht im Hauptspeicher befindet, sondern ausgelagert wurde. Dies löst eine synchrone Programmunterbrechung (engl.: trap) aus. Das Betriebssystem sorgt nun dafür, dass der angeforderte Speicherbereich wieder in den Hauptspeicher geladen wird, damit das Programm darauf zugreifen kann. Die Seite kann nun durchaus physisch an anderer Stelle liegen als ursprünglich, die Memory Management Unit berücksichtigt das entsprechend. Die virtuelle Adresse bleibt davon unverändert. Ein Seitenfehler verursacht also keinen Abbruch, sondern eine Aktion, die dem Prozess anschließend die normale Weiterverarbeitung erlaubt.

Das Zurückholen solcher Seiten ist ein Vorgang, der deutlich länger dauert, als nur auf eine Hauptspeicheradresse zuzugreifen. Deshalb verlangsamen Seitenfehler, wenn sie in hohem Umfang auftreten, die Programmgeschwindigkeit erheblich. So lange es dem Page stealer gelingt, einen gewissen Freiraum zu halten, ist der Seitenfehler zwar relativ schnell behoben. Problematisch wird die Lage, wenn der Trap noch auf den Page stealer warten muss, bis dieser Platz geschaffen hat. Die Situation kann eskalieren, sodass sich das System hauptsächlich noch mit der Behandlung von Seitenfehlern beschäftigt und gravierende Geschwindigkeitseinbußen verzeichnet. Page stealer und die Traps greifen beide auf die Auslagerungsdatei zu und lasten ab einem gewissen Punkt die betroffenen Festplatten komplett aus. Dieser Effekt wird als Seitenflattern bzw. thrashing bezeichnet.

Seitenersetzungsstrategien von Betriebssystemen

Typische Strategien um die Verwendung von RAM und langsameren sekundären Speichern für alle Prozesse zu optimieren sind:

  • NRU („not recently used“): Teilt Seiten anhand des Use-Bits und Dirty-Bits aus der Seitentabelle in vier Klassen und entfernt zufällig eine aus der untersten, nicht-leeren Klasse.
  • FIFO („first in, first out“): Jede Seite bekommt Zeitstempel; „älteste raus, hinten rein, vorne raus“
  • Second-Chance-Algorithmus: Variante von FIFO, die verhindert, dass Seiten ausgelagert werden, die noch häufig benutzt werden.
  • LFU („least frequently used“): Jede Seite hat ein Feld, das Aufschluss über letzte Nutzung gibt; bei Seitenfehler müssen alle Seiten auf bislang nicht benutzte Zeit durchsucht werden
  • Working-Set-Algorithmus: Ersetzt gleich den ganzen Arbeitsbereich (working set) eines Prozesses. Er zählt zu den Prepaging-Strategien, da Seiten bevor benötigt geladen werden.
  • Clock-Algorithmus: Funktionsweise analog zum Second-Chance-Algorithmus. Die Seiten werden in Form einer virtuellen Uhr mit Zeigern abgebildet. Im Verdrängungsfall wird der Uhrzeiger so lange um ein Element weitergeschaltet, bis eine Seite mit einem zurückgesetzten R-Bit gefunden wird. Seiten mit gesetztem R-Bit werden bei der Überquerung des Zeigers zurückgesetzt. Bei großer Anzahl an Hauptspeicherseiten ist dieses Verfahren zu langsam. Daher werden z. B. bei BSD-UNIX zwei Zeiger mit konstantem Abstand zur Laufzeitverbesserung verwendet. Der vordere Zeiger setzt das R-Bit im Seitendeskriptor zurück, der hintere prüft das R-Bit und führt bei zurückgesetztem Bit die Verdrängung durch.
  • Belady-Theorem der optimalen Verdrängung: Hierbei werden die Seiten verdrängt, die in Zukunft am längsten nicht referenziert werden. Nicht umsetzbar, da das Programmverhalten nicht vorhergesagt werden kann.

Gemeinsamkeiten und Unterschiede

Gemeinsam sind den virtuellen Speicherverwaltungen heutzutage folgende Grundprinzipien:

  1. Alle von Prozessen verwendeten Adressen werden nur noch als virtuelle Adressen behandelt.
  2. Der durch die Gesamtheit aller möglichen virtuellen Adressen definierte virtuelle Adressraum, der den virtuellen Speicher bildet, wird genauso wie der tatsächlich vorhandene physische Arbeitsspeicher in gleich große Speicherabschnitte unterteilt. Die für diese Speicherabschnitte verwendeten deutschen Begriffe Kachel, Speicherseite oder Seitenrahmen sind synonym. Im Englischen wird dieser Speicherabschnitt pageframe genannt. Eine Seite (page) des virtuellen Adressraums wird auf eine Kachel (pageframe) des physischen Adressraums abgebildet.
  3. Die Memory Management Unit übersetzt die virtuellen Adressen in reale physische Adressen.

Die verschiedenen virtuellen Speicherverwaltungen unterscheiden sich

  1. in der Speichergröße, die eine Speicherseite belegt,
  2. in der Art, wie die Memory Management Unit aus der virtuellen Adresse eine physische Adresse berechnet und
  3. in ihrer Seitenersetzungsstrategie, welche die Reaktion auf einen so genannten Seitenfehler, die Adressierung einer nicht im physischen Speicher vorhandenen virtuellen Adresse, festlegt.

Beispiele

  • AMD64-Architektur: Eine virtuelle Adresse ist 48 Bit lang. Es wird eine vierstufige Seitentabelle verwendet. Die 48 Bit teilen sich auf in je 9 Bit für die vier Seitentabellen plus 12 Bit Offset.
  • IA32-Architektur: Eine virtuelle Adresse ist 32 Bit lang. Es wird eine zweistufige Seitentabelle verwendet. Die 32 Bit teilen sich auf in je 10 Bit für die zwei Seitentabellen plus 12 Bit Offset.
  • IA32-Architektur mit PAE: Eine virtuelle Adresse ist 32 Bit lang. Es wird eine dreistufige asymmetrische Seitentabelle verwendet. Die 32 Bit teilen sich auf in 2 Bit für die erste Seitentabelle und je 9 Bit für die zwei weiteren Seitentabellen plus 12 Bit Offset.

Bei der IA-32-Architektur ist der Arbeitsspeicher in Speicherseiten aufgeteilt, deren mögliche Größen und Anfangsadressen durch die Hardware vorgegeben sind. Wird auf eine Adresse zugegriffen, der zurzeit keine physische Speicherseite zugeordnet ist, so muss das Betriebssystem die Memory Management Unit anweisen, an dieser Stelle eine bestimmte freie Speicherseite einzublenden. Steht keine freie Speicherseite mehr zur Verfügung, so muss eine andere Speicherseite frei gemacht werden, wobei der Inhalt vom Betriebssystem z. B. auf die Festplatte ausgelagert wird. Diesen Vorgang bezeichnet man als Paging. Die Größe des virtuellen Adressraums kann aus der Definition der virtuellen Adresse berechnet werden. So ist beispielsweise in einer IA-32-Architektur eine virtuelle Adresse 32 Bit breit, zweimal je 10 Bit für eine zweistufige Seitentabelle und 12 Bit für den Offset. Somit lassen sich 210 x 210 x 212 Byte adressieren. Das sind 232 Byte, also 4 GiB.

Einzelnachweise

  1. E. Jessen: Origin of the Virtual Memory Concept. IEEE Annals of the History of Computing. Band 26. 4/2004, Seite 71 ff.
  2. Eike Jessen: Die Entwicklung des virtuellen Speichers. In: Springer Berlin / Heidelberg (Hrsg.): Informatik-Spektrum. 19, Nr. 4, 1996, S. 216-219. doi:10.1007/s002870050034.

Siehe auch

Weblinks


Wikimedia Foundation.