1 / 49 Vorlesung Betriebssysteme II Thema 4: Hauptspeicherverwaltung Robert Baumgartl 27. April 2015
2 / 49 Freispeicherverwaltung Motivation Applikationen und das Betriebssystem selbst fordern zur Laufzeit Speicher an (und geben diesen später wieder zurück). Notwendigkeit der Verwaltung notwendig, zur Laufzeit Speicher an Anfordernde (Applikationen, BS) auszureichen und wieder entgegenzunehmen Schnittstelle: Menge an Funktionen, die Speicher anfordern und diesen wieder zurückgeben
Freispeicherverwaltung Probleme 3 / 49 Fragmentierung: intern Verlust durch feste Segmentgröße ( Verschnitt ) extern Verlust durch inkohärente Speicherung ( Verstreuung ) Kompensation durch Kompaktifizierung Table Verlust durch Speicherbedarf der Verwaltungsstrukturen Laufzeitkomplexität der Suche nach freiem Segment der Rückgabe des Segments (Wiedereinordnung) Zwei grundlegende Management-Techniken: 1. Bitmaps 2. Listen
Bitmaps 4 / 49 Anforderung wird auf einen oder mehrere Blöcke einer fixen Größe abgebildet Karte des Hauptspeichers Blöcke (allocation units) einheitlicher Größe pro Block ein Bit: = 0 Block frei = 1 Block belegt belegt frei belegt belegt frei belegt belegt A B C D E frei n Allokations einheit 11111000 11111111 11001111 11111000 Bitmap
5 / 49 Bitmaps Blockungsfaktor Parameter: Blockungsfaktor n, beeinflusst: Speicherbedarf für die Bitmap interne Fragmentierung Gefahr der externen Fragmentierung fixe Größe der Verwaltungsstruktur keine weiteren Verwaltungsinformationen in Bitmap speicherbar
Freispeicherliste 6 / 49 Idee: Suche nach einem passenden freien Segment ggf. Abtrennen des nicht benötigten Restes d.h., es werden stets exakt passende Segmente ausgegeben ( keine interne Fragmentierung) pro Segment ein Element einer verkettete Liste (einfach, doppelt, Ring), enthält: Anfangsaddresse Länge belegt/frei-information Zeiger auf Nachfolge-Element weitere Informationen, z. B. Eigentümer Start A 0 5 5 3 B 8 6 C 14 4 18 2 D 20 6 E 26 3 29 3
Blöcke mit integrierten Headern 7 / 49 Variante: Header ist in Blöcke integriert (belegt/frei-bit, Länge, evntl. Zeiger auf NF) Header 0 Länge Länge Länge 1 0 1 1 Länge Länge...
8 / 49 Freispeicherliste Suchstrategien Suchoperation bei Forderung eines Segmentes der Größe m: First Fit Durchsuchen der Liste beginnend von Start erstes freies Segment m wird genutzt ggf. Abtrennen des Überschusses (Teilung des Segments; 1 freies 1 belegtes + 1 freies) Tendenz: anfangs belegte Segmente, später mehr freie Segmente Next Fit Start der Suche an letzer Erfolgsposition sonst wie First Fit Tendenz zu größerer Fragmentierung als First Fit
9 / 49 Freispeicherliste Suchstrategien II Best Fit Suche in Liste nach bestpassendstem Element (kleinstes Element, dessen Größe l m) Suchaufwand! Gefahr der Generierung unbenutzbar kleiner Restsegmente Worst Fit Suche nach größtmöglichem Element, um Nachteil von Best Fit zu begegnen externe Fragmentierung! Bei Freigabe eines Blockes: Markierung als frei Vereinigung mit freien Nachbarblöcken, wenn möglich
10 / 49 Freispeicherliste Techniken zur Effizienzsteigerung Verzögertes Vereinigen (Deferred Coalescing): freigegebene Segmente nicht sofort mit freien Nachbarsegmenten vereinigen Effizienzsteigerung wenn Objekte einer Größe angefordert und freigegeben werden Vereinigung erst nach Verzögerung oder durch extra Aktivität Objektcache (Slab Allocator) Begrenzungsmarken (Boundary Tags) Endebegrenzung jedes Segmentes durch zum Header identischen Footer vereinfacht Vereinigung mit unmittelbar vorangehendem (freien) Nachbarblock Problem: Table Fragmentation
11 / 49 Freispeicherliste Techniken zur Effizienzsteigerung II Zusätzliche Verkettung freier Segmente schnellere Suche kein zusätzlicher Speicherplatz nötig, da nur im ungenutzten Speicher angelegt H F H F H F H F H F... Abbildung: Zusätzliche Verkettung freier Segmente
12 / 49 Getrennte Freispeicherlisten (Segregated Fits) Idee: Array von Listen unterschiedlicher Segmentgröße(nklassen), um Suchaufwand zu reduzieren Variante 1: Einfacher getrennter Speicher (Simple Segregated Storage) eine Liste pro Segmentgröße keine Teilung von Segmenten Liste leer 1-2 Seiten mittels sbrk() anfordern, in gleichgroße Blöcke teilen, in Liste einordnen kein Transfer zwischen Listen ( keine Vereinigung mit benachbarten Segmenten) ziemlich effizient im durchschnittlichen Fall Worst Case?
Getrennte Freispeicherlisten (Segregated Fits) 13 / 49 Variante 2: Getrennte Fits Liste leer Liste mit nächster Größe durchsucht, Teilung eines gefundenen Segments a) exakte Listen b) Strikte Größenklassen mit Rundung c) Listen mit Größenintervallen ggf. Wiederholung der Suche in Listen mit größeren Segmenten Vereinigung benachbarter freier Segmente (sofort oder verzögert)
14 / 49 Buddy-Verfahren Idee: System reicht Blöcke fester Größe k = 2 N Bytes aus N Listen mit (exakter) Segmentgröße ausgereicht wird stets ein Block mit der Größe, die die Anforderung am knappsten befriedigt (z. B. Anforderung 47 KiB Auslieferung 64 KiB) wenn kein Block passender Größe vorhanden: 1. Teilung eines nächstgrößeren (freien) Blockes 2. Auslieferung einer Hälfte 3. andere Hälfte (der Buddy ) wird als frei in die entsprechende Liste einsortiert Initial enthält eine Liste genau einen Block, den gesamten (freien) Hauptspeicher Bei Rückgabe wird geprüft, ob der Block ggf. mit seinem Buddy vereinigt werden kann (und in der Liste der nächstgrößeren Blöcke eingeordnet werden kann)
15 / 49 Buddy-Verfahren Beurteilung Aufwand bei Rückgabe des Speichers geringer als mit Freispeicherliste wirkt externer Fragmentierung entgegen, da stets maximal wieder vereinigt wird Hauptnachteil: Speicherplatzverschwendung (Verschnitt; interne Fragmentierung)
16 / 49 Virtueller Speicher Motivation Ziel: Schutz der Aktivitäten voreinander die Größe des Hauptspeichers übersteigende Prozesssysteme Konzept: Erweiterung des Hauptspeichers durch Massenspeicher Privatisierung der Adressräume Partitionierung der virtuellen und des physischen Adressraums (einheitliche, feste Größe; z. B. 4 KiB)
17 / 49 Virtueller Speicher Seiten vs. Kacheln virtueller Adressraum logische Seiten (virtuelle Seiten, Pages) physischer Adressraum (gleichgroße) Kacheln (Seitenrahmen, Page Frames)
18 / 49 Virtueller Speicher Seiten vs. Kacheln Seiten virtueller Speicher Prozeß 1 A B MMU+OS C D Prozeß 2 P Q R physischer Hauptspeicher P A B C frei Kacheln Q R frei D...... Abbildung: Abbildung logischer Seiten auf physische Kacheln
Gestreute Speicherung Umsetzung virtueller in physische Adresse 19 / 49 bei jeder (!) Speicherreferenz ausgeführt durch Hardware (Memory Management Unit MMU im Prozessor) Indexierung einer Tabelle (Seitentabelle, Page Table) Seitentabelle durch BS verwaltet, existiert pro Prozess Seitennummer virtuelle Adresse Index 0x0000 0x1000 Hauptspeicher Seitenadressen Prot P 0x8000 0x1000 RW RO 1 0 0x3000 RWX 1......... 0x4000 RO 1 Seitentabelle + 0x2000 physische Adresse 0x4000... selektiertes Wort
Seitentabelleneintrag (Page Table Entry PTE) Aufbau (Beispiel) 20 / 49 C D R M Prot P Page Frame Number PFN Page Frame Number Adresse der entsprechenden physischen Kachel P Present-Bit Seite ist im Hauptspeicher (oder auf Massenspeicher ausgelagert) Prot Protection Lese-/Schreib-/Ausführungs-Operation sind (nicht) erlaubt M Modified ( dirty ) Kachel wurde beschrieben ( muss vor Auslagerung auf Massenspeicher zurückgeschrieben werden) R Referenced Seite wurde durch den Prozess (irgendwann einmal) gelesen, referenziert CD Cache disable Seiteninhalt darf nicht gecacht werden (wichtig bei memory-mapped devices)
21 / 49 Größe der einstufigen Seitentabelle Problem: Größe der Seitentabelle (muß hintereinander im Speicher stehen) Beispiel Seitengröße 4 KiB, 32 Bit Adressbreite Index 12 Bit (2 12 = 4096) Seitennummer 20 Bit groß (32-12=20) Seitentabelle kann 2 20 Einträge enthalten resultierende Größe der Seitentabelle 4 MByte (pro Prozess!)
22 / 49 Größe der Seitentabelle Lösung: Baum von Seitentabellen ( Hierarchie) langsamerer Zugriff, da mehrere Subtabellen aufgesucht werden müssen Subtabellen dafür kürzer und flexibler (auf Anforderung anlegbar) zwei- (Intel i386), drei- und vierstufige Hierarchien Verbesserung des Timings durch einen Cache, der Adressumsetzungen virtuell physisch aufbewahrt: Translation Lookaside Buffer (TLB)
Beispiel: Zweistufige Seitentabelle (i386) 23 / 49 PD Index PT Index Byte Index virtuelle Adresse Register CR3 gewähltes Byte gewählte Seite PD Eintrag PTE Page Directory 1024 Einträge Page Tables 1024 Einträge physischer Adreßraum
Demand Paging 24 / 49 Idee: Benötigte Seiten werden erst bei Bedarf in den Hauptspeicher geladen. Ist der physische Speicher restlos ausgenutzt, so muss zuvor eine andere Seite ausgelagert werden. Prinzipieller Ablauf 1. Prozess referenziert eine Adresse (neuer Befehl, Zugriff auf Datum) 2. MMU führt Adressübersetzung aus 3. BS prüft: referenzierte Seite im physischen Speicher Ausführung der Instruktion, Weiterarbeit referenzierte Seite momentan ausgelagert Seitenfehler (Page Fault, Software-Interrupt)
25 / 49 Seitenfehler (Pagefault) 1. Prozess wird angehalten (blockiert) 2. BS sucht freie HS-Kachel 3. falls keine freie HS-Kachel verfügbar Auswahl einer auszulagernden Seite, Auslagerung auf Festplatte 4. Einlesen der referenzierten Seite in (nun) freie HS-Kachel von Festplatte 5. Weiterarbeit des blockierten Prozesses Pro Seitenfehler bis zu 2 Festplattenzugriffe notwendig! Einfachere Alternative: Swapping: ganze Prozesse werden ausgelagert!
26 / 49 Einlagerungsstrategien Demand Paging: Einblenden einer Seite bei Referenz (spätestmöglicher Zeitpunkt, Lazy Evaluation) Prepaging: Seiten werden im voraus eingeblendet. Sinnvoll bei kontinuierlicher Ablage auf Massenspeicher; angewandt z.b. bei Start eines neuen Prozesses (Windows NT).
Seitenaustauschverfahren 27 / 49 Frage: Welche Seite soll ausgelagert werden? Ähnlichkeit zur Ersetzungsstrategie in Caches Strafe (Penalty) sehr hoch, da Massenspeicherzugriff: 1 Instruktion benötigt ca. 0.3 ns bei 3 GHz Takt 1 Festplattenoperation benötigt ca. 10 ms Zeit für 30 10 6 Instruktionen Worst Case?
28 / 49 Seitenaustauschverfahren Optimales Verfahren; LRU Optimales Verfahren lagert diejenige Seite aus, die am längsten nicht benötigt wird (in Zukunft) schwierig ohne eingebauten Hellseher wichtig zum Vergleich realer Verfahren Least Recently Used (LRU) Heuristik: Seiten die lange nicht referenziert wurden, werden auch in Zukunft kaum gebraucht exaktes LRU schwierig ( älteste Seite auslagern ) vgl. Cache Approximation: NRU
29 / 49 Seitenaustauschverfahren Not Recently Used (NRU) Not Recently Used (NRU) Ausnutzung des Referenced- und des Modified-Bits im Seitentabelleneintrag periodisches Rücksetzen des R-Bits durch BS (z.b. durch Timerinterrupt gesteuert) R-Bit wird automatisch (durch MMU) gesetzt, sobald Seite referenziert wurde M-Bit gesetzt, wenn Seiteninhalt modifiziert wurde ( dirty ) vor Auslagerung zurückschreiben
Seitenaustauschverfahren Not Recently Used (NRU), contd. 4 Klassen von Seiten unterscheidbar: R M Beschreibung 0 0 Seite wurde nicht referenziert 0 1 Seite wurde lange nicht referenziert, aber (irgendwann) verändert 1 0 Seite wurde referenziert, aber nicht modifiziert 1 1 Seite wurde referenziert und geändert bei Bedarf zunächst Auslagerung von {00}-Seiten wenn keine verfügbar, dann {01}-Seiten, dann {10}-Seiten, usw. 30 / 49
Seitenaustauschverfahren FIFO; 2nd Chance 31 / 49 First In, First Out (FIFO) Idee: ältere Seiten zuerst auslagern keine Berücksichtigung der Referenz Second Chance verbessert FIFO Auslagerungskandidat (AK): älteste Seite R == 0 Seite wird ausgelagert R == 1 R := 0, Kandidat: nächstälteste Seite Anordnung der Seiten in Ringliste, Zeiger auf AK Uhralgorithmus
Seitenaustauschverfahren NFU; Aging 32 / 49 Not Frequently Used (NFU) Betrachtung der Referenzierungshäufigkeit pro Seite ein Zähler, periodisches Aufaddieren des R-Bits Auslagerung der am seltensten genutzten Seite (kleinster Zählerstand) später eingelagerte Seiten benachteiligt benötigt: Vergessen veralteter Zählerstände Aging Modifikation von NFU: alle Zähler vor Aufaddieren des R-Bits 1 Bit nach rechts geschoben R-Bit wird an höchste Bitposition des Zählers geschrieben
Seitenaustauschverfahren Aging, contd. Tick 1 2 3 4 5 R Bits 1 0 1 0 1 1 1 1 0 0 1 0 1 1 0 1 0 1 1 0 0 0 1 0 0 1 1 0 0 0 0 10000000 11000000 11100000 11110000 01111000 1 00000000 10000000 11000000 01100000 10110000 2 10000000 01000000 00100000 00010000 10001000 3 00000000 00000000 10000000 01000000 00100000 4 10000000 11000000 01100000 10110000 01011000 5 10000000 01000000 10100000 01010000 00101000 Abbildung: Beispiel für den Aging-Algorithmus Shift-Operation realisiert Vergessen alter Zählerstände Häufigkeit und Zeitpunkt der Referenzierung relevant 33 / 49
34 / 49 Konzept der Arbeitsmenge (Working Set) Empirische Beobachtung: eine bestimmte Anzahl eingeblendeter Seiten ist optimal. Anzahl zu gering hohe Seitenfehlerrate, Anzahl zu groß Speicherverschwendung, möglicherweise kein Prozess mehr bereit. Prinzip: Die Arbeitsmenge W (t, ) sind diejenigen Seiten eines Prozesses, die zwischen dem aktuellen Zeitpunkt t und einem Zeitpunkt t in der Vergangenheit referenziert wurden.
Beispiel für eine Arbeitsmenge Referenz- kette 2 3 4 5 24 24 24 24 24 15 24, 15 24,15 24,15 24,15 18 15, 18 24,15,18 24,15,18 24,15,18 23 18, 23 15,18,23 24,15,18,23 24,15,18,23 24 23, 24 18,23,24 17 24, 17 23, 24, 17 18, 23, 24, 17 15, 18, 23, 24, 17 18 17, 18 24, 17, 18 23, 24, 17, 18 24 18, 24 17, 18, 24 18 24, 18 17, 24, 18 17 18, 17 24, 18, 17 17 17 18, 17 15 17, 15 17, 15 18, 17, 15 24, 18, 17, 15 24 15, 24 17, 15, 24 17, 15, 24 17 24, 17 17, 15, 24 24 27, 24 18 24, 18 17, 24, 18 17, 24, 18 15, 17, 24, 18 Tabelle: Beispiel der Entwicklung der Arbeitsmenge eines Prozesses für unterschiedliche (Bach: The Design of the UNIX Operating System. 1986, S. 287) 35 / 49
Konzept der Arbeitsmenge (Working Set) 36 / 49 Es gilt W (t, + 1) W (t, ) d.h., die Arbeitsmenge wächst monoton mit. Weiterhin gilt für die Menge der referenzierten Seiten 1 W (t, ) min(, N) wobei N die Gesamtzahl der referenzierten Seiten eines Prozesses bezeichnet. Der Parameter kann als Fenstergröße in die Referenzierungsvergangenheit des Prozesses aufgefasst werden.
Abhängigkeit der Größe der Arbeitsmenge von 37 / 49 W (t, ) 0
38 / 49 Abhängigkeit der Größe der Arbeitsmenge von gesättigtes Verhalten: ab einem bestimmten Punkt ( 0 ) ändert sich die Größe der Arbeitsmenge nicht mehr gravierend (Ursache: Lokalitätsprinzip) minimale Größe der Arbeitsmenge W (t, 0 ), bestimmt die Grenze zwischen niedriger und hoher Pagefault-Rate Working Set unterliegt zyklischen Veränderungen; man unterscheidet transiente und stabile Zustände
Idee für eine Ersetzungsstrategie... basierend auf dem Working Set 39 / 49 W für jeden Prozess beobachten zyklisch alle diejenigen Seiten eines Prozesses entfernen, die nicht zu W gehören Prozess darf nur aktiviert werden, wenn seine Arbeitsmenge im Hauptspeicher eingeblendet Probleme: exakte Messung, Logging des WS aufwendig Approximation Wahl von : zu klein PF-Rate des Prozesses steigt zu groß Speicherverschwendung keine Adaption bei Größenänderung der Arbeitsmenge
Beladys Anomalie Vergrößerung von W führt normalerweise zu Verringerung der Page-Fault-Rate des betroffenen Prozesses, jedoch... 5 virtuelle Seiten Ersetzungsstrategie FIFO (willkürliche ) Referenzierungskette: 0 1 2 3 0 1 4 0 1 2 3 4 Ref. Kette 0 1 2 3 0 1 4 0 1 2 3 4 jüngste Seite älteste Seite PF 0 1 0 2 3 0 1 4 4 4 2 3 3 1 2 3 0 0 1 2 3 1 1 1 4 2 0 0 0 1 4 2 4 Abbildung: Beladys Beispiel mit W = 3 Seitenrahmen 40 / 49
Beladys Anomalie, contd. 41 / 49 Ref. Kette 0 1 2 3 0 1 4 0 1 2 3 4 jüngste Seite 0 1 2 3 3 3 4 0 1 2 3 0 1 2 2 2 3 4 0 1 2 0 1 1 1 2 3 4 0 1 älteste Seite 0 0 0 1 2 3 4 0 4 3 2 1 PF Abbildung: Beladys Beispiel mit W = 4 Seitenrahmen Vergrößerung des WS führt zu Erhöhung der PF-Rate (W = 3 9PF, W = 4 10PF) unerwartetes Verhalten, Anomalie konstruiertes Beispiel abhängig vom Seitenersetzungsverfahren; LRU unempfindlich
42 / 49 Weitere Aspekte zur Seitenersetzung optimale Seitengröße? lokale vs. globale Ersetzungsstrategien variable vs. konstante Größe des Working Set viele weitere Ersetzungsstrategien alternative Mechanismen der Suche in Seitentabellen
Schnittstelle zum Betriebssystem UNIX malloc() und free() Semantik: Anforderung von Heap-Speicher, bzw. dessen Rückgabe Funktionen der C-Bibliothek ( portabel) eine der Hauptquellen für Programmfehler ist fehlerhafter Umgang mit diesen Funktionen weitere Funktionen: realloc(), calloc() unter UNIX gewöhnlich mittels brk() realisiert (jedoch auch mit mmap()) Implementierung stark systemabhängig viele Allokatoren vergrößern Heap zwar, verkleinern jedoch nicht (Optimierung) Seiten werden bei malloc() weder initialisiert noch zwangsweise eingeblendet bekannteste Implementation: Doug Lea s Allocator 43 / 49
Speicherabbild eines Prozesses 44 / 49 High Umgebung, Argumente Stack Heap uninitialisierte Daten (BSS) "break" null initialisiert Low initialisierte Daten Text aus Datei eingelesen durch exec()
Der Systemruf brk() 45 / 49 int brk(void *end_data_segment); setzt das Ende des Heaps auf end_data_segment, vorausgesetzt Wert ist plausibel, das System hat noch genügend Speicher, maximale Heapgröße des Prozesses wird nicht überschritten genutzt z. B. zur Implementierung von malloc() & Co. weitere Funktion der C-Bibliothek: sbrk() malloc() und brk() nicht gleichzeitig verwendbar im Vergleich zu malloc() viel elementarer
46 / 49 Stackanforderung mittels alloca() void *alloca(size_t size); alloziiert size Bytes auf dem Stack (!) keine Rückgabefunktion benötigt (Warum?) nicht für alle Systeme verfügbar The alloca function is machine and compiler dependent. On many systems its implementation is buggy. Its use is discouraged. (man alloca, 2.6er Linux-System) Implementierung durch Inline-Code ( nicht als Argument einer Parameterliste nutzbar)
47 / 49 Ausschalten des Pagings (Pinning) Verhinderung des Auslagerns a) einzelner Seiten mittels mlock() b) des gesamten Adressraums mittels mlockall() für (weiche) Echtzeit- und sicherheitskritische Applikationen Rückbau mit munlock()/munlockall() vergrößert Pagefault-Rate für nichtpinnende Prozesse
48 / 49 Memory-mapped Files aka speichereingeblendete Dateien mmap(), munmap(), mremap(), msync() blendet Dateien (oder Geräte) in den Hauptspeicher ein Granularität: Seiten gemeinsame oder exklusive Einblendung möglich d. h. eingeblendete Dateien werden wie Hauptspeicher manipuliert (ersetzt klassische open/read/write/close-schnittstelle) modern
49 / 49 Was haben wir gelernt? Hauptspeicherverwaltung: Bitmaps, Listen, Buddy-Verfahren Virtueller Speicher: Funktionsweise, Ablauf des Pagefault, relevante Datenstrukturen Ersetzungsstrategien (LFU, NFU, Aging & Co., Working Set ) API zum Hauptspeicher von unix-artigen BS