22.02.2014 Aufrufe

Teil 4: Speicherverwaltung

Teil 4: Speicherverwaltung

Teil 4: Speicherverwaltung

MEHR ANZEIGEN
WENIGER ANZEIGEN

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

1 / 49<br />

Vorlesung Betriebssysteme II<br />

Thema 4: Hauptspeicherverwaltung<br />

Robert Baumgartl<br />

24. 04. 2012


2 / 49<br />

Freispeicherverwaltung<br />

Motivation<br />

Applikationen und das Betriebssystem selbst fordern zur<br />

Laufzeit Speicher an (und geben diesen später wieder zurück).<br />

→ Notwendigkeit der Verwaltung<br />

◮ notwendig, zur Laufzeit Speicher an Anfordernde<br />

(Applikationen, BS) auszureichen und wieder<br />

entgegenzunehmen<br />

◮ Schnittstelle: Menge an Funktionen, die Speicher<br />

anfordern und diesen wieder zurückgeben


Freispeicherverwaltung<br />

Probleme<br />

3 / 49<br />

◮ Fragmentierung:<br />

intern – Verlust durch feste Segmentgröße<br />

(„Verschnitt“)<br />

extern – Verlust durch inkohärente Speicherung<br />

(„Verstreuung“) → Kompensation durch<br />

Kompaktifizierung<br />

Table ∼ – Verlust durch Speicherbedarf der<br />

Verwaltungsstrukturen<br />

◮ Laufzeitkomplexität<br />

◮ der Suche nach freiem Segment<br />

◮ der Rückgabe des Segments (Wiedereinordnung)<br />

Zwei grundlegende Management-Techniken:<br />

1. Bitmaps<br />

2. Listen


Bitmaps<br />

4 / 49<br />

◮ Anforderung wird auf einen oder mehrere Blöcke einer<br />

fixen Größe abgebildet<br />

◮ „Karte“ des Hauptspeichers<br />

◮ Blöcke (allocation units) einheitlicher Größe<br />

◮ pro Block ein Bit:<br />

◮ = 0 → Block frei<br />

◮ = 1 → Block belegt<br />

belegt frei belegt belegt frei belegt belegt<br />

A B C D E<br />

frei<br />

n<br />

Allokations−<br />

einheit<br />

11111000<br />

11111111<br />

11001111<br />

11111000<br />

Bitmap


5 / 49<br />

Bitmaps<br />

Blockungsfaktor<br />

◮ Parameter: Blockungsfaktor n, beeinflusst:<br />

◮ Speicherbedarf für die Bitmap<br />

◮ interne Fragmentierung<br />

◮ Gefahr der externen Fragmentierung<br />

◮ fixe Größe der Verwaltungsstruktur<br />

◮ keine weiteren Verwaltungsinformationen in Bitmap<br />

speicherbar


Freispeicherliste<br />

6 / 49<br />

◮ Idee: Suche nach einem “‘passenden”’ freien Segment<br />

◮ ggf. Abtrennen des nicht benötigten Restes<br />

◮ d.h. , es werden stets exakt passende Segmente<br />

ausgegeben (→ keine interne Fragmentierung)<br />

◮ pro Segment ein Element einer verkettete Liste (einfach,<br />

doppelt, Ring), enthält:<br />

◮ Anfangsaddresse<br />

◮ Länge<br />

◮ belegt/frei-Information<br />

◮ Zeiger auf Nachfolge-Element<br />

◮ weitere Informationen, z. B. Eigentümer<br />

Start<br />

A 0 5 5 3 B 8 6 C 14 4<br />

18 2 D 20 6 E 26 3 29 3


Blöcke mit integrierten Headern<br />

7 / 49<br />

Variante: Header ist in Blöcke integriert (belegt/frei-Bit, Länge,<br />

evntl. Zeiger auf NF)<br />

Header<br />

0<br />

Länge<br />

Länge<br />

Länge<br />

1 0 1 1<br />

Länge<br />

Länge<br />

...


8 / 49<br />

Freispeicherliste<br />

Suchstrategien<br />

Suchoperation bei Forderung eines Segmentes der Größe m:<br />

First Fit<br />

◮ Durchsuchen der Liste beginnend von Start<br />

◮ erstes freies Segment ≥ m wird genutzt<br />

◮ ggf. Abtrennen des Überschusses (<strong>Teil</strong>ung des Segments;<br />

1 freies → 1 belegtes + 1 freies)<br />

◮ Tendenz: anfangs belegte Segmente, später mehr freie<br />

Segmente<br />

Next Fit<br />

◮ Start der Suche an letzer Erfolgsposition<br />

◮ sonst wie First Fit<br />

◮ Tendenz zu größerer Fragmentierung als First Fit


9 / 49<br />

Freispeicherliste<br />

Suchstrategien II<br />

Best Fit<br />

◮ Suche in Liste nach bestpassendstem Element (kleinstes<br />

Element, dessen Größe l ≥ m)<br />

◮ Suchaufwand!<br />

◮ Gefahr der Generierung unbenutzbar kleiner<br />

Restsegmente<br />

Worst Fit<br />

◮ Suche nach größtmöglichem Element, um Nachteil von<br />

Best Fit zu begegnen<br />

◮ → externe Fragmentierung !<br />

Bei Freigabe eines Blockes:<br />

◮ Markierung als frei<br />

◮ Vereinigung mit freien Nachbarblöcken, wenn möglich


10 / 49<br />

Freispeicherliste<br />

Techniken zur Effizienzsteigerung<br />

Verzögertes Vereinigen (Deferred Coalescing):<br />

◮ freigegebene Segmente nicht sofort mit freien<br />

Nachbarsegmenten vereinigen<br />

◮ Effizienzsteigerung wenn Objekte einer Größe angefordert<br />

und freigegeben werden<br />

◮ Vereinigung erst nach Verzögerung oder durch extra<br />

Aktivität<br />

◮ → Objektcache (Slab Allocator)<br />

Begrenzungsmarken (Boundary Tags)<br />

◮ Endebegrenzung jedes Segmentes durch zum Header<br />

identischen Footer<br />

◮ vereinfacht Vereinigung mit unmittelbar vorangehendem<br />

(freien) Nachbarblock<br />

◮ Problem: Table Fragmentation


11 / 49<br />

Freispeicherliste<br />

Techniken zur Effizienzsteigerung II<br />

Zusätzliche Verkettung freier Segmente<br />

◮ schnellere Suche<br />

◮ kein zusätzlicher Speicherplatz nötig, da nur im<br />

ungenutzten Speicher angelegt<br />

H F H F H F H F H F<br />

...<br />

Abbildung: Zusätzliche Verkettung freier Segmente


12 / 49<br />

Getrennte Freispeicherlisten (Segregated Fits)<br />

Idee: Array von Listen unterschiedlicher<br />

Segmentgröße(nklassen), um Suchaufwand zu reduzieren<br />

Variante 1: Einfacher getrennter Speicher (Simple Segregated<br />

Storage)<br />

◮ eine Liste pro Segmentgröße<br />

◮ keine <strong>Teil</strong>ung von Segmenten<br />

◮ Liste leer → 1-2 Seiten mittels sbrk() anfordern, in<br />

gleichgroße Blöcke teilen, in Liste einordnen<br />

◮ kein Transfer zwischen Listen ( keine Vereinigung mit<br />

benachbarten Segmenten)<br />

◮ ziemlich effizient im durchschnittlichen Fall<br />

◮ Worst Case?


Getrennte Freispeicherlisten (Segregated Fits)<br />

13 / 49<br />

Variante 2: Getrennte Fits<br />

◮ Liste leer → Liste mit nächster Größe durchsucht, <strong>Teil</strong>ung<br />

eines gefundenen Segments<br />

a) exakte Listen<br />

b) Strikte Größenklassen mit Rundung<br />

c) Listen mit Größenintervallen<br />

◮ ggf. Wiederholung der Suche in Listen mit größeren<br />

Segmenten<br />

◮ Vereinigung benachbarter freier Segmente (sofort oder<br />

verzögert)


14 / 49<br />

Buddy-Verfahren<br />

Idee: System reicht Blöcke fester Größe k = 2 N Bytes aus<br />

◮ N Listen mit (exakter) Segmentgröße<br />

◮ ausgereicht wird stets ein Block mit der Größe, die die<br />

Anforderung am knappsten befriedigt (z. B. Anforderung 47<br />

KiB → Auslieferung 64 KiB)<br />

◮ wenn kein Block passender Größe vorhanden:<br />

1. <strong>Teil</strong>ung eines nächstgrößeren (freien) Blockes<br />

2. Auslieferung einer Hälfte<br />

3. andere Hälfte (der „Buddy“) wird als frei in die<br />

entsprechende Liste einsortiert<br />

◮ Initial enthält eine Liste genau einen Block, den gesamten<br />

(freien) Hauptspeicher<br />

◮ Bei Rückgabe wird geprüft, ob der Block ggf. mit seinem<br />

Buddy vereinigt werden kann (und in der Liste der<br />

nächstgrößeren Blöcke eingeordnet werden kann)


15 / 49<br />

Buddy-Verfahren<br />

Beurteilung<br />

◮ Aufwand bei Rückgabe des Speichers geringer als mit<br />

Freispeicherliste<br />

◮ wirkt externer Fragmentierung entgegen, da stets maximal<br />

wieder vereinigt wird<br />

◮ Hauptnachteil: Speicherplatzverschwendung (Verschnitt;<br />

interne Fragmentierung)


16 / 49<br />

Virtueller Speicher<br />

Motivation<br />

Ziel:<br />

◮ Schutz der Aktivitäten voreinander<br />

◮ die Größe des Hauptspeichers übersteigende<br />

Prozesssysteme<br />

Konzept:<br />

◮ „Erweiterung“ des Hauptspeichers durch Massenspeicher<br />

◮ Privatisierung der Adressräume<br />

◮ Partitionierung der virtuellen und des physischen<br />

Adressraums (einheitliche, feste Größe; z. B. 4 KiB)


17 / 49<br />

Virtueller Speicher<br />

Seiten vs. Kacheln<br />

◮ virtueller Adressraum → logische Seiten (virtuelle Seiten,<br />

Pages)<br />

◮ physischer Adressraum → (gleichgroße) Kacheln<br />

(Seitenrahmen, Page Frames)


18 / 49<br />

Virtueller Speicher<br />

Seiten vs. Kacheln<br />

Seiten<br />

virtueller Speicher<br />

Prozeß 1<br />

A<br />

B MMU+OS<br />

C<br />

D<br />

Prozeß 2<br />

P<br />

Q<br />

R<br />

physischer Hauptspeicher<br />

P<br />

A<br />

B<br />

C<br />

frei Kacheln<br />

Q<br />

R<br />

frei<br />

D<br />

...<br />

...<br />

Abbildung: Abbildung logischer Seiten auf physische Kacheln


Gestreute Speicherung<br />

Umsetzung virtueller in physische Adresse<br />

19 / 49<br />

◮ bei jeder (!) Speicherreferenz<br />

◮ ausgeführt durch Hardware (Memory Management Unit –<br />

MMU im Prozessor)<br />

◮ Indexierung einer Tabelle (Seitentabelle, Page Table)<br />

◮ Seitentabelle durch BS verwaltet, existiert pro Prozess<br />

Seitennummer<br />

virtuelle Adresse<br />

Index<br />

0x0000<br />

0x1000<br />

Hauptspeicher<br />

Seitenadressen Prot P<br />

0x8000<br />

0x1000<br />

RW<br />

RO<br />

1<br />

0<br />

0x3000 RWX 1<br />

...<br />

...<br />

...<br />

0x4000 RO 1<br />

Seitentabelle<br />

+<br />

0x2000<br />

physische<br />

Adresse<br />

0x4000<br />

...<br />

selektiertes<br />

Wort


Seitentabelleneintrag (Page Table Entry – PTE)<br />

Aufbau (Beispiel)<br />

20 / 49<br />

C<br />

D<br />

R<br />

M<br />

Prot<br />

P Page Frame Number<br />

◮ PFN – Page Frame Number – Adresse der<br />

entsprechenden physischen Kachel<br />

◮ P – Present-Bit – Seite ist im Hauptspeicher (oder auf<br />

Massenspeicher ausgelagert)<br />

◮ Prot – Protection – Lese-/Schreib-/Ausführungs-Operation<br />

sind (nicht) erlaubt<br />

◮ M – Modified (“dirty”) – Kachel wurde beschrieben (→<br />

muss vor Auslagerung auf Massenspeicher<br />

zurückgeschrieben werden)<br />

◮ R – Referenced – Seite wurde durch den Prozess<br />

(irgendwann einmal) gelesen, referenziert<br />

◮ CD – Cache disable – Seiteninhalt darf nicht gecacht<br />

werden (wichtig bei memory-mapped devices)


21 / 49<br />

Größe der einstufigen Seitentabelle<br />

Problem: Größe der Seitentabelle (muß hintereinander im<br />

Speicher stehen)<br />

Beispiel<br />

Seitengröße 4 KiB, 32 Bit Adressbreite<br />

→ Index 12 Bit (2 12 = 4096)<br />

→ Seitennummer 20 Bit groß (32-12=20)<br />

→ Seitentabelle kann 2 20 Einträge enthalten<br />

→ resultierende Größe der Seitentabelle 4 MByte (pro<br />

Prozess!)


22 / 49<br />

Größe der Seitentabelle<br />

Lösung: Baum von Seitentabellen (→ Hierarchie)<br />

◮ langsamerer Zugriff, da mehrere Subtabellen aufgesucht<br />

werden müssen<br />

◮ Subtabellen dafür kürzer und flexibler (auf Anforderung<br />

anlegbar)<br />

◮ zwei- (Intel i386), drei- und vierstufige Hierarchien<br />

◮ Verbesserung des Timings durch einen Cache, der<br />

Adressumsetzungen virtuell → physisch aufbewahrt:<br />

Translation Lookaside Buffer (TLB)


Beispiel: Zweistufige Seitentabelle (i386)<br />

23 / 49<br />

PD−Index<br />

PT−Index<br />

Byte−Index<br />

virtuelle<br />

Adresse<br />

Register CR3<br />

gewähltes Byte<br />

gewählte<br />

Seite<br />

PD−Eintrag<br />

PTE<br />

Page Directory<br />

1024 Einträge<br />

Page Tables<br />

1024 Einträge<br />

physischer Adreßraum


Demand Paging<br />

24 / 49<br />

Idee: Benötigte Seiten werden erst bei Bedarf in den<br />

Hauptspeicher geladen. Ist der physische Speicher restlos<br />

ausgenutzt, so muss zuvor eine andere Seite ausgelagert<br />

werden.<br />

Prinzipieller Ablauf<br />

1. Prozess referenziert eine Adresse (neuer Befehl, Zugriff<br />

auf Datum)<br />

2. MMU führt Adressübersetzung aus<br />

3. BS prüft:<br />

◮ referenzierte Seite im physischen Speicher → Ausführung<br />

der Instruktion, Weiterarbeit<br />

◮ referenzierte Seite momentan ausgelagert → Seitenfehler<br />

(Page Fault, Software-Interrupt)


25 / 49<br />

Seitenfehler (Pagefault)<br />

1. Prozess wird angehalten (blockiert)<br />

2. BS sucht freie HS-Kachel<br />

3. falls keine freie HS-Kachel verfügbar → Auswahl einer<br />

auszulagernden Seite, Auslagerung auf Festplatte<br />

4. Einlesen der referenzierten Seite in (nun) freie HS-Kachel<br />

von Festplatte<br />

5. Weiterarbeit des blockierten Prozesses<br />

Pro Seitenfehler bis zu 2 Festplattenzugriffe notwendig!<br />

Einfachere Alternative: Swapping: ganze Prozesse werden<br />

ausgelagert!


26 / 49<br />

Einlagerungsstrategien<br />

◮ Demand Paging: Einblenden einer Seite bei Referenz<br />

(spätestmöglicher Zeitpunkt, Lazy Evaluation)<br />

◮ Prepaging: Seiten werden im voraus eingeblendet.<br />

Sinnvoll bei kontinuierlicher Ablage auf Massenspeicher;<br />

angewandt z.B. bei Start eines neuen Prozesses<br />

(Windows NT).


Seitenaustauschverfahren<br />

27 / 49<br />

Frage: Welche Seite soll ausgelagert werden?<br />

◮ Ähnlichkeit zur Ersetzungsstrategie in Caches<br />

◮ Strafe (Penalty) sehr hoch, da Massenspeicherzugriff:<br />

◮ 1 Instruktion benötigt ca. 0.3 ns bei 3 GHz Takt<br />

◮ 1 Festplattenoperation benötigt ca. 10 ms<br />

◮ → Zeit für ≈ 30 · 10 6 Instruktionen<br />

◮ Worst Case?


28 / 49<br />

Seitenaustauschverfahren<br />

Optimales Verfahren; LRU<br />

Optimales Verfahren<br />

◮ lagert diejenige Seite aus, die am längsten nicht benötigt<br />

wird (in Zukunft)<br />

◮ schwierig ohne eingebauten Hellseher<br />

◮ wichtig zum Vergleich realer Verfahren<br />

Least Recenty Used (LRU)<br />

◮ Heuristik: Seiten die lange nicht referenziert wurden,<br />

werden auch in Zukunft kaum gebraucht<br />

◮ exaktes LRU schwierig („älteste Seite auslagern“)<br />

◮ vgl. Cache<br />

◮ Approximation: NRU


29 / 49<br />

Seitenaustauschverfahren<br />

Not Recently Used (NRU)<br />

Not Recenty Used (NRU)<br />

◮ Ausnutzung des Referenced- und des Modified-Bits im<br />

Seitentabelleneintrag<br />

◮ periodisches Rücksetzen des R-Bits durch BS (z.B. durch<br />

Timerinterrupt gesteuert)<br />

◮ R-Bit wird automatisch (durch MMU) gesetzt, sobald Seite<br />

referenziert wurde<br />

◮ M-Bit gesetzt, wenn Seiteninhalt modifiziert wurde („dirty“)<br />

→ vor Auslagerung zurückschreiben


Seitenaustauschverfahren<br />

Not Recently Used (NRU), contd.<br />

◮ 4 Klassen von Seiten unterscheidbar:<br />

R M Beschreibung<br />

0 0 Seite wurde nicht referenziert<br />

0 1 Seite wurde lange nicht referenziert, aber (irgendwann)<br />

verändert<br />

1 0 Seite wurde referenziert, aber nicht modifiziert<br />

1 1 Seite wurde referenziert und geändert<br />

◮ bei Bedarf zunächst Auslagerung von {00}-Seiten<br />

◮ wenn keine verfügbar, dann {01}-Seiten, dann {10}-Seiten,<br />

usw.<br />

30 / 49


Seitenaustauschverfahren<br />

FIFO; 2nd Chance<br />

31 / 49<br />

First In, First Out (FIFO)<br />

◮ Idee: ältere Seiten zuerst auslagern<br />

◮ keine Berücksichtigung der Referenz<br />

Second Chance<br />

◮ verbessert FIFO<br />

◮ Auslagerungskandidat (AK): älteste Seite<br />

◮ R == 0 → Seite wird ausgelagert<br />

◮ R == 1 → R := 0, Kandidat: nächstälteste Seite<br />

◮ Anordnung der Seiten in Ringliste, Zeiger auf AK →<br />

„Uhralgorithmus“


Seitenaustauschverfahren<br />

NFU; Aging<br />

32 / 49<br />

Not Frequently Used (NFU)<br />

◮ Betrachtung der Referenzierungshäufigkeit<br />

◮ pro Seite ein Zähler, periodisches Aufaddieren des R-Bits<br />

◮ Auslagerung der am seltensten genutzten Seite (kleinster<br />

Zählerstand)<br />

◮ später eingelagerte Seiten benachteiligt<br />

◮ benötigt: Vergessen veralteter Zählerstände<br />

Aging<br />

◮ Modifikation von NFU:<br />

◮ alle Zähler vor Aufaddieren des R-Bits 1 Bit nach rechts<br />

geschoben<br />

◮ R-Bit wird an höchste Bitposition des Zählers geschrieben


Seitenaustauschverfahren<br />

Aging, contd.<br />

Tick<br />

1 2 3 4 5<br />

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<br />

0<br />

10000000 11000000 11100000<br />

11110000<br />

01111000<br />

1<br />

00000000<br />

10000000<br />

11000000<br />

01100000<br />

10110000<br />

2<br />

10000000<br />

01000000<br />

00100000<br />

00010000<br />

10001000<br />

3<br />

00000000<br />

00000000<br />

10000000<br />

01000000<br />

00100000<br />

4<br />

10000000<br />

11000000<br />

01100000<br />

10110000<br />

01011000<br />

5<br />

10000000<br />

01000000<br />

10100000<br />

01010000<br />

00101000<br />

Abbildung: Beispiel für den Aging-Algorithmus<br />

◮ Shift-Operation realisiert „Vergessen“ alter Zählerstände<br />

◮ Häufigkeit und Zeitpunkt der Referenzierung relevant<br />

33 / 49


34 / 49<br />

Konzept der Arbeitsmenge (Working Set)<br />

Empirische Beobachtung: eine bestimmte Anzahl<br />

eingeblendeter Seiten ist optimal.<br />

◮ Anzahl zu gering → hohe Seitenfehlerrate,<br />

◮ Anzahl zu groß → Speicherverschwendung,<br />

möglicherweise kein Prozess mehr bereit.<br />

Prinzip: Die Arbeitsmenge W (t, ∆) sind diejenigen Seiten<br />

eines Prozesses, die zwischen dem aktuellen Zeitpunkt t und<br />

einem Zeitpunkt t − ∆ in der Vergangenheit referenziert<br />

wurden.


Beispiel für eine Arbeitsmenge<br />

Referenz-<br />

∆<br />

kette 2 3 4 5<br />

24 24 24 24 24<br />

15 24, 15 24,15 24,15 24,15<br />

18 15, 18 24,15,18 24,15,18 24,15,18<br />

23 18, 23 15,18,23 24,15,18,23 24,15,18,23<br />

24 23, 24 18,23,24 ⋆ ⋆<br />

17 24, 17 23, 24, 17 18, 23, 24, 17 15, 18, 23, 24, 17<br />

18 17, 18 24, 17, 18 ⋆ 23, 24, 17, 18<br />

24 18, 24 ⋆ 17, 18, 24 ⋆<br />

18 ⋆ 24, 18 ⋆ 17, 24, 18<br />

17 18, 17 24, 18, 17 ⋆ ⋆<br />

17 17 18, 17 ⋆ ⋆<br />

15 17, 15 17, 15 18, 17, 15 24, 18, 17, 15<br />

24 15, 24 17, 15, 24 17, 15, 24 ⋆<br />

17 24, 17 ⋆ ⋆ 17, 15, 24<br />

24 ⋆ 27, 24 ⋆ ⋆<br />

18 24, 18 17, 24, 18 17, 24, 18 15, 17, 24, 18<br />

Tabelle: Beispiel der Entwicklung der Arbeitsmenge eines Prozesses<br />

für unterschiedliche ∆ (Bach: The Design of the UNIX Operating<br />

System. 1986, S. 287) 35 / 49


Konzept der Arbeitsmenge (Working Set)<br />

36 / 49<br />

Es gilt<br />

W (t, ∆ + 1) ⊇ W (t, ∆)<br />

d.h., die Arbeitsmenge wächst monoton mit ∆. Weiterhin gilt für<br />

die Menge der referenzierten Seiten<br />

1 ≤ W (t, ∆) ≤ min(∆, N)<br />

wobei N die Gesamtzahl der referenzierten Seiten eines<br />

Prozesses bezeichnet. Der Parameter ∆ kann als<br />

Fenstergröße in die Referenzierungsvergangenheit des<br />

Prozesses aufgefasst werden.


Abhängigkeit der Größe der Arbeitsmenge von ∆<br />

|W (t, ∆)|<br />

∆ 0 ∆<br />

37 / 49


38 / 49<br />

Abhängigkeit der Größe der Arbeitsmenge von ∆<br />

◮ „gesättigtes“ Verhalten: ab einem bestimmten Punkt (∆ 0 )<br />

ändert sich die Größe der Arbeitsmenge nicht mehr<br />

gravierend (Ursache: Lokalitätsprinzip)<br />

◮ minimale Größe der Arbeitsmenge |W (t, ∆ 0 )|, bestimmt<br />

die Grenze zwischen niedriger und hoher Pagefault-Rate<br />

◮ Working Set unterliegt zyklischen Veränderungen; man<br />

unterscheidet transiente und stabile Zustände


Idee für eine Ersetzungsstrategie<br />

. . . basierend auf dem Working Set<br />

39 / 49<br />

◮ W für jeden Prozess beobachten<br />

◮ zyklisch alle diejenigen Seiten eines Prozesses entfernen,<br />

die nicht zu W gehören<br />

◮ Prozess darf nur aktiviert werden, wenn seine<br />

Arbeitsmenge im Hauptspeicher eingeblendet<br />

Probleme:<br />

◮ exakte Messung, Logging des WS aufwendig <br />

Approximation<br />

◮ Wahl von ∆:<br />

◮ zu klein → PF-Rate des Prozesses steigt<br />

◮ zu groß → Speicherverschwendung<br />

◮ keine Adaption bei Größenänderung der Arbeitsmenge


Beladys Anomalie<br />

Vergrößerung von W führt normalerweise zu Verringerung der<br />

Page-Fault-Rate des betroffenen Prozesses, jedoch . . .<br />

◮ 5 virtuelle Seiten<br />

◮ Ersetzungsstrategie FIFO<br />

◮ (willkürliche ) Referenzierungskette: 0 → 1 → 2 → 3 → 0<br />

→ 1 → 4 → 0 → 1 → 2 → 3 → 4<br />

Ref.−Kette<br />

0 1 2 3 0 1 4 0 1 2 3 4<br />

jüngste Seite<br />

älteste Seite<br />

PF<br />

0 1<br />

0<br />

2 3 0 1 4 4 4 2 3 3<br />

1 2 3 0<br />

0 1 2 3<br />

1 1 1 4 2<br />

0 0 0 1 4<br />

2<br />

4<br />

Abbildung: Beladys Beispiel mit W = 3 Seitenrahmen<br />

40 / 49


Beladys Anomalie, contd.<br />

41 / 49<br />

Ref.−Kette<br />

0 1 2 3 0 1 4 0 1 2 3 4<br />

jüngste Seite 0 1 2 3 3 3 4 0 1 2 3<br />

0 1 2 2 2 3 4 0 1 2<br />

0 1 1 1 2 3 4 0 1<br />

älteste Seite 0 0 0 1 2 3 4 0<br />

4<br />

3<br />

2<br />

1<br />

PF<br />

Abbildung: Beladys Beispiel mit W = 4 Seitenrahmen<br />

◮ Vergrößerung des WS führt zu Erhöhung der PF-Rate<br />

(W = 3 → 9PF, W = 4 → 10PF)<br />

◮ unerwartetes Verhalten, Anomalie<br />

◮ konstruiertes Beispiel<br />

◮ abhängig vom Seitenersetzungsverfahren; LRU<br />

unempfindlich


42 / 49<br />

Weitere Aspekte zur Seitenersetzung<br />

◮ optimale Seitengröße?<br />

◮ lokale vs. globale Ersetzungsstrategien<br />

◮ variable vs. konstante Größe des Working Set<br />

◮ viele weitere Ersetzungsstrategien<br />

◮ alternative Mechanismen der Suche in Seitentabellen


Schnittstelle zum Betriebssystem UNIX<br />

malloc() und free()<br />

◮ Semantik: Anforderung von Heap-Speicher, bzw. dessen<br />

Rückgabe<br />

◮ Funktionen der C-Bibliothek (→ portabel)<br />

◮ eine der Hauptquellen für Programmfehler ist fehlerhafter<br />

Umgang mit diesen Funktionen<br />

◮ weitere Funktionen: realloc(), calloc()<br />

◮ unter UNIX gewöhnlich mittels brk() realisiert (jedoch<br />

auch mit mmap())<br />

◮ Implementierung stark systemabhängig<br />

◮ viele Allokatoren vergrößern Heap zwar, verkleinern<br />

jedoch nicht (Optimierung)<br />

◮ Seiten werden bei malloc() weder initialisiert noch<br />

zwangsweise eingeblendet<br />

◮ bekannteste Implementation: Doug Lea’s Allocator<br />

43 / 49


Speicherabbild eines Prozesses<br />

44 / 49<br />

High<br />

Umgebung, Argumente<br />

Stack<br />

Heap<br />

uninitialisierte Daten<br />

(BSS)<br />

"break"<br />

null−initialisiert<br />

Low<br />

initialisierte Daten<br />

Text<br />

aus Datei eingelesen<br />

durch exec()


Der Systemruf brk()<br />

45 / 49<br />

int brk(void *end_data_segment);<br />

◮ setzt das Ende des Heaps auf end_data_segment,<br />

vorausgesetzt<br />

◮ Wert ist plausibel,<br />

◮ das System hat noch genügend Speicher,<br />

◮ maximale Heapgröße des Prozesses wird nicht<br />

überschritten<br />

◮ genutzt z. B. zur Implementierung von malloc() & Co.<br />

◮ weitere Funktion der C-Bibliothek: sbrk()<br />

◮ malloc() und brk() nicht gleichzeitig verwendbar<br />

◮ im Vergleich zu malloc() viel elementarer


46 / 49<br />

Stackanforderung mittels alloca()<br />

void *alloca(size_t size);<br />

◮ alloziiert size Bytes auf dem Stack (!)<br />

◮ keine Rückgabefunktion benötigt (Warum?)<br />

◮ nicht für alle Systeme verfügbar<br />

“The alloca function is machine and compiler<br />

dependent. On many systems its implementation<br />

is buggy. Its use is discouraged.” (man alloca,<br />

2.6er Linux-System)<br />

◮ Implementierung durch Inline-Code ( nicht als Argument<br />

einer Parameterliste nutzbar)


47 / 49<br />

Ausschalten des Pagings (Pinning)<br />

◮ Verhinderung des Auslagerns<br />

a) einzelner Seiten mittels mlock()<br />

b) des gesamten Adressraums mittels mlockall()<br />

◮ für (weiche) Echtzeit- und sicherheitskritische<br />

Applikationen<br />

◮ Rückbau mit munlock()/munlockall()<br />

◮ vergrößert Pagefault-Rate für nichtpinnende Prozesse


48 / 49<br />

Memory-mapped Files<br />

aka ‘speichereingeblendete Dateien’<br />

◮ mmap(), munmap(), mremap(), msync()<br />

◮ blendet Dateien (oder Geräte) in den Hauptspeicher ein<br />

◮ Granularität: Seiten<br />

◮ gemeinsame oder exklusive Einblendung möglich<br />

◮ d. h. eingeblendete Dateien werden wie Hauptspeicher<br />

manipuliert (ersetzt klassische<br />

open/read/write/close-Schnittstelle)<br />

◮ modern


49 / 49<br />

Was haben wir gelernt?<br />

◮ Hauptspeicherverwaltung: Bitmaps, Listen,<br />

Buddy-Verfahren<br />

◮ Virtueller Speicher: Funktionsweise, Ablauf des Pagefault,<br />

relevante Datenstrukturen<br />

◮ Ersetzungsstrategien (LFU, NFU, Aging & Co., Working<br />

Set )<br />

◮ API zum Hauptspeicher von unix-artigen BS

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!