Memory Management
Speicherverwaltung / Memory Management
Das OS wird zuerst in den Hauptspeicher eingefĂŒgt und stellt dann Prozessen Speicher zur verfĂŒgung.
Wir wollen Speicher effektiv aufteilen und verwalten:
Partitioning - Speicheraufteilung auf Prozesse
Positioning (= Allocation + Relocation) - Speichern von Code und Daten, Virtual-Memory Management
Protection - Speicherschutz
Sharing - gemeinsamer Zugriff mit mutual exclusion
Performance - schnelle, effektive logische und physikalische Organisation
Partitioning
Haupt-Speicher-Aufteilung auf Prozesse.
Prozesse beinhalten Programm und Daten, Kontext.
OS wird immer zuerst eingefĂŒgt.
Zu wenig Speicherplatz:
Swapping / Auslagern von Prozessen vorrĂŒbergehend auf SekundĂ€rspeicher auslagern.
Overlays / Ăberladen von Programmen Programm Anteile im PrimĂ€r- oder SekundĂ€rspeicher.
Speicherplatz wird nicht effizient ausgenĂŒtzt:
Fragmentierung Teile des Speichers bleiben ungenĂŒtzt.
Interne Fragmentierung UngenĂŒtzter Speicherplatz innerhalb einer Partition.
Externe Fragmentierung ZerstĂŒckelung des Speicherbereichs auĂerhalb der Partitionen.
Löst sich mit compaction (Zusammenschieben, teure Operation).
1) Fixed Partitioning
Statisch Partitionen mit fix vordefinierten GröĂe.
Problem Speichernutzung ineffizient, interne Fragmentierung
Gleiche Partitions-GröĂen
Es ist bei gleicher PartitionsgröĂe egal wie man sie mit Prozessen belegt.
Programm kann zu groĂ fĂŒr Partition sein obwohl Speicher leer
Ineffizient - kleines Programm kann gesamte Partition blockieren
Interne Fragmentierung
Unterschiedliche Partitions-GröĂen
Wir wollen Partitionen optimal belegen.
Eine Queue fĂŒr jede Partition
Partitionen nach GröĂe sortiert. Je nach GröĂe, kommt Prozess in eine andere Queue.
Problem: kleine Prozesse können in Warteschlange sein obwohl gröĂere Partitionen leer sind.
Eine Queue fĂŒr alle Partitionen
Nimmt kleinstmöglichste Partition
2) Dynamic Partitioning
Dynamisch Partitionen mit variabler LĂ€nge und Anzahl.
Problem Externe Fragmentierung
Weist jedem Prozess eine Partition zu die exakt so groĂ ist.
FĂŒr die ersten Prozesse optimal, danach haben "Löcher" ohne Partition und wieder fixe GröĂen.
Placement Stategien beim EinfĂŒgen
Auswahl der Partition in die ein Prozess eingefĂŒgt werden soll:
Best fit - Geringste Platzverschwendung / Geringster Verschnitt
First fit - erste freie Partition von oben
Next fit - wie first fit, fĂ€ngt aber von der letzten freien Stelle wo eingefĂŒgt wurde an
3) Buddy System
Fixed und dynamic partitioning sind nicht mehr in Benutzung.
Versucht SchwÀchen von statischer und dynamischer Partitionierung auszugleichen:
konfigurierbare GröĂen
GröĂenvergabe nur mit Zweierpotenzen ï»ż wobei fĂŒr ï»ż Schranken angegeben werden.
Buddy = Speicher-Block
Ablauf: Anforderung von BlockgröĂeï»ż
-
Suche nach Block mit
ï»ż
fĂŒr die Schranken
ï»ż
.
Sucht nach kleinstem bestehenden passenden Block.
Am Anfang ist der gesamte Speicher ein groĂer Block.
-
Falls nicht gefunden, zerteile nĂ€chstgröĂeren Block in
ï»ż
kleinere (so lange bis gefunden).
Zerkleinert gröĂere Blöcke.
zB angenommen wir findenï»żdann zerteilen wir den Blockï»żmal herunter.
Nach dem Löschen: Vereine benachbarte Blöcke die nicht belegt wurden.
__________
Relocation - Logische Adressierung
Referenzen auf physikalischen Speicher mĂŒssen verĂ€nderbar sein.
Wir wollen Daten im Speicher verschieben können (= dynamisch positionieren) da wir andere absolute Adressen haben bei
zB Swapping, Compaction - wenn Prozess wieder ins Speicher geholt wird
ProgrammausfĂŒhrung auf unterschiedlichen Rechnern mit unterschiedlichen Speicherbelegungen.
AddressĂŒbersetzung
Zur Laufzeit: logische und relative Adressen aus Programm ï»ż absolute Adressen.
Memory Management Unit (Hardware) und Page-table / Segment-table unterstĂŒtzen Ăbersetzung.
Physische (absolute) Adresse
Nicht verÀnderbar - Absolute Position in Hauptspeicher
Logische Adresse
VerÀnderbare Variablenzuweisung.
Pointer zu Position im Speicher - unabhÀngig von Speicherorganisation.
Relative Adresse
Position relativ zur logischen Adresse.
Einfache AddressĂŒbersetzung
Erfolgt bei jedem Speicherzugriff durch Hardware.
Wir speichern 2 wichtige physische Addressen
Base Register Programm-Anfang: Zeigt auf Start-Adresse vom laufenden Prozesses
Bound Register Programm-Ende: damit wir nur auf gĂŒltige Addressbereiche zugreifen
Umsetzung:
- Ăbersetzte absolute Addresse = Startaddresse + Relative Addresse als Offset
- Danach vergleich mit Boundregister damit Addressbereich / Bound nicht ĂŒberschritten wird
__________
Relocation - Virtual memory management
Virtual Memory
Wir abstrahieren darĂŒber welcher Anteil vom Prozess im Hauptspeicher ist.
Wir ĂŒbernehmen nur notwendige Frames vom Prozess ins Hauptspeicher.
Logischer Addressraum kann viel gröĂer sein als der physischer Addressraum.
mehr Speicherplatz, ParallelitÀt
AusfĂŒhrung von Prozessen die viel gröĂer sind als der Speicherplatz
Anteil von Prozess Frames / Segmente im SekundĂ€rspeicher heiĂt virtual memory.
ï»ż
Resident Set
Anteil vom Prozess im Hauptspeicher.
Fixed Allocation Bei Prozesserstellung fixe Anzahl an Frames zugewiesen
Variable Allocation Allokiierten Frames können sich wÀhrend Prozesslebensdauer noch Àndern
Page Fault (Exception Handling)
Adresse nicht im Hauptspeicher gefunden - Suche im SekundÀrspeicher ( Demand Paging ).
Thrashing
Management beansprucht mehr Ressourcen als Prozesse.
zB zu viele Page faults da Resident set zu klein
Prozessor muss sehr oft vom Sekunderspeicher laden (IO Operation).
Lösung: Swapping von Prozessen, Resident set vergröĂern
1) Segmentierung
Wir wollen nicht gesamtes Programm fĂŒr Prozess in Hauptspeicher laden sondern Segmente davon definieren die dann in den Partitionen eingefĂŒgt werden.
Es kann zu Fragmentierung kommen.
Segment Programm-Block mit beliebiger LÀnge die zusammengehörenden Code und Daten enthÀlt.
Segment-Tabelle EnthÀlt SegmentlÀnge und Start (Base der physischen Adresse).
AdressĂŒbersetzung mit Segment-tabelle
Logische Addresse besteht aus Offset und Segmentnummer (= Index aus Segmenttabelle)
Logische Addresse: ( Segment-Index | Offset )
â
Segment table: ( Length | Base )
â
Physische Addresse: Base + Offset
2) Paging
Effizienter als Segmentierung
Page Frame
Arbeitsspeicher im Vorherein in gleich groĂe Frames unterteilt.
Relativ klein verglichen mit Segmenten.
In der Free Frame List stehen alle freien Frames im Speicher
Page
Logische Addressbereiche in gleich groĂe Pages unterteilt.
Pages werden zur Laufzeit in Frames hineingeladen (wobei der Frame dann LĂŒcken haben kann) .
Pages und Frames sind gleich lang (GröĂe in Zweierpotenzen)
Page-table
Page table um fĂŒr jede Page eines Prozesses die Position im Frame zu finden. Alle bits stehen fĂŒr booleans.
Present Bit Seite im Hauptspeicher?
Frame Number pointer zu Frame
Modified Bit Seite seit dem letzten Load verÀndert? (Konsistenz mit festplatte)
Control Bits r/w, kernel/user (fĂŒr protection, security) , locking (nicht entfernen)
AdressĂŒbersetzung
Compiler, Linker muss nichts ĂŒber Unterteilung nichts wissen - passiert durch Paging-Hardware
Logischer Addressbereich Physischer Addressbereich
( Page Number | Offset ) ( Frame Number | Offset )
| â
index ââââââââââââââââââââââââââââââââ table entry
Page Table
Eintrag in page table wird gefunden indem mit dem pointer welche die page table base enthÀlt addiert wird.
Multilevel Page Tables
Die page-table der Prozesse selbst muss im Arbeitsspeicher sein - Kann mit der Zeit sehr groĂ werden.
Page-table wird selbst in pages unterteilt, die in der root-page-table nachgeschlagen werden.
Ineffizient: 2 Speicherzugriffe vor jedem eigentlichen Speicherzugriff.
Inverted Page Table IPT
Platz sparen indem sich Prozesse eine groĂe Tabelle teilen
Keine page-table pro Prozess sondern eine groĂe page-table fĂŒr alle Prozesse im Arbeitsspeicher.
Suche durch assoziativen Suchalgorithmus oder Hashing mit Hardware.
Translation Lookaside Buffer TLB
Um zu vermeiden dass 2 physikalische Speichezugriffe notwendig sind (page table, daten lesen).
Cache in der CPU fĂŒr die EintrĂ€ge der page-table auf die zuletzt zugegriffen wurde.
Assoziativer Zugriff beim Suchen (sofort zugreifbar).
TLB wird bei jedem context switch gelöscht.
Bei TLB-miss wird Cache erweitert.
Effizient wegen LokalitÀtsprinzip.
Fetch policy
Wann kommen Seiten in den Hauptspeicher? Ăhnlich wie: Pre-Cleaning vs. Demand Cleaning
Demand Paging laden bei Bedarf (viele Page faults am Anfang)
Prepaging lÀdt mehr im Voraus (LokalitÀtsprinzip) - viele Seiten nicht benötigt
Replace policy
Welche pages werden ersetzt wenn eine neue ins Hauptspeicher geladen wird?
local replacement Austauschstrategie auf Seiten des gleichen Prozesses
global replacement Austauschstrategie auf alle Seiten des Hauptspeichers
Austausch-Strategien
OPT Policy (optimal)
Optimale Strategie nicht implementierbar sondern als MaĂstab fĂŒr andere Strategien.
WÀhlt die Page die am spÀtesten referenziert wird.
Minimale #page-faults
LRU Policy (last recently used)
Ersetzt die Seite die am lĂ€ngsten nicht benĂŒtzt worden ist.
Nutzt zeitliche LokalitÀt, sehr nahe zur optimaler strategie
Viel overhead, viel zum Protokollieren, aufwendig zu Implementieren:
Speichern der Zugriffszeiten + Suche
FIFO Policy
Ersetzt die Àlteste Seite (die zuerst geladen wurde).
Einfach zu implementieren: Pointer welcher zyklisch die page-frames iteriert
Keine Information ĂŒber Frequenz der Verwendung der Seite
Deutlich mehr #page-faults
Clock Policy
Ringpuffer aus Seiten die fĂŒr Austausch in Frage kommen.
Jede Seite hat ein used-bit (welche sagt ob neulich auf sie zugegriffen wurde oder nicht).
Nicht viel mehr page-faults als LRU.
Pointer wird am Anfang zufÀllig gesetzt.
- Es wird nach 0 gesucht und alle 1-EintrÀge dazwischen werden geflipped.
- Nachdem 0 gefunden wurde, wird die Seite ersetzt und der Bit auf 1 gesetzt
- Danach wird der pointer auf die nÀchste Position gestellt bis zur nÀchste Suche.
In diesem Szenario, wird in der darauf erneut folgenden Replacement, gleich die page ersetzt auf die der pointer das letzte Mal gezeigt hat, weil dort eine 0 steht und das bit auf 1 geflipped.
Working Set Strategie
Zur Bestimmung der richtigen GröĂe des Resident-Sets
zu wenige Frames: viele Page-Faults
zu viele Frames: weniger Arbeitsspeicher verfĂŒgbar, geringere ParallelitĂ€t
Working Set von einem Prozess
ï»ż = Set an pages, auf die ï»ż virtuelle Zeiteinheiten vor Zeitpunkt ï»ż zugegriffen wurde.
Virtuelle Zeiteinheiten: Nur Zeitfortschreitung im Prozess - zB preemptions nicht betrachtet.
Eigenschaften:
wÀchst am Anfang schnell
stabilisiert sich mit ProzessausfĂŒhrung
wĂ€chst wieder wenn wir anderen Prozess ausfĂŒhren
Anwendung
Wir checken periodisch das Working Set fĂŒr alle Prozesse.
Resident Set ï»ż Working Set
Gib Speicher Frei.
Lösche pages die nicht im Working Set sind.
Resident Set ï»ż Working Set
Allokiiere fehlende Frames aus SekundÀrspeicher, durch Swapping anderer Prozesse
Eigenschaften
Overhead: ZusÀtzliches Logging und Ordnen von Seitenreferenzen
Optimales ï»ż variiert und ist zur Laufzeit unbekannt
Best Practice
Beobachtung der #page-faults statt working-set pro Zeitintervall (fĂŒr einzelne Prozesse) mit einem vordefinierten threshold.
Bei threshhold-Ăberschreitung bin ich im thrashing und suspend das Prozess.
Protection
Speicherschutz: Prozesse sollen nur auf die eigenen Seiten zugreifen können.
Virtueller Addressraum als Schutz
Adressen die protected sind, werden in Page-Table nicht eingetragen, dadurch page-fault.
Protection Keys
Variante 1 ï»ż key-pair fĂŒr Prozess und Frame im Speicher
Bei Speicherzugriff mĂŒssen keys gleich sein
Variante 2 ï»ż key-pair fĂŒr Prozess und TLB
TLB ein key pro Eintrag
Jeder Prozess hat eine Menge von keys Registers
Bei Speicherzugriff mĂŒssen keys gleich sein