Paging
Paging
Paging
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
<strong>Paging</strong><br />
Einfaches <strong>Paging</strong><br />
<strong>Paging</strong> mit virtuellem Speicher
Einfaches <strong>Paging</strong><br />
Wie bisher (im Gegensatz zu virtuellem Speicherkonzept): Prozesse sind<br />
entweder ganz im Speicher oder komplett ausgelagert.<br />
Im Gegensatz zu Partitionierung werden Prozessen nicht<br />
notwendigerweise zusammenhängende Speicherbereiche zugeordnet.<br />
Hauptspeicher aufgeteilt in viele gleichgroße Seitenrahmen.<br />
Speicher eines Prozesses aufgeteilt in Seiten derselben Größe.<br />
Zuordnung von Seiten zu Seitenrahmen beim Laden von Prozessen<br />
− Logische Adressen der Form „Seitennummer, Offset“<br />
− Pro Prozess eine „Seitentabelle“<br />
− Seitentabelle übersetzt Seitennummern in Nummern von Seitenrahmen im<br />
physikalischen Speicher<br />
Interne Fragmentierung nur bei letzter Seite eines Prozesses
Einfaches <strong>Paging</strong>: Beispiel<br />
Rahmen-<br />
nummer<br />
0<br />
1<br />
2<br />
3<br />
4<br />
5<br />
6<br />
7<br />
8<br />
9<br />
10<br />
11<br />
12<br />
13<br />
14<br />
Hauptspeicher<br />
0<br />
1<br />
2<br />
3<br />
4<br />
5<br />
6<br />
7<br />
8<br />
9<br />
Hauptspeicher<br />
0<br />
1<br />
2<br />
3<br />
4<br />
5<br />
6<br />
7<br />
8<br />
9<br />
Hauptspeicher<br />
0<br />
1<br />
2<br />
3<br />
4<br />
5<br />
6<br />
7<br />
8<br />
9<br />
Hauptspeicher<br />
Prozess A<br />
geladen<br />
Prozess B<br />
geladen<br />
Prozess C<br />
geladen<br />
10<br />
11<br />
12<br />
13<br />
14<br />
10<br />
11<br />
12<br />
13<br />
14<br />
10<br />
11<br />
12<br />
13<br />
14<br />
A.0<br />
A.1<br />
A.2<br />
A.3<br />
A.0<br />
A.1<br />
A.2<br />
A.3<br />
A.0<br />
A.1<br />
A.2<br />
A.3<br />
B.0<br />
B.1<br />
B.2<br />
B.0<br />
B.1<br />
B.2<br />
C.0<br />
C.1<br />
C.2<br />
C.3<br />
Prozess D<br />
mit 6 Seiten<br />
soll jetzt<br />
geladen<br />
werden!
Einfaches <strong>Paging</strong>: Beispiel<br />
Rahmennummer<br />
0<br />
1<br />
2<br />
3<br />
4<br />
5<br />
6<br />
7<br />
8<br />
9<br />
10<br />
11<br />
12<br />
13<br />
14<br />
Hauptspeicher<br />
A.0<br />
A.1<br />
A.2<br />
A.3<br />
C.0<br />
C.1<br />
C.2<br />
C.3<br />
Prozess B<br />
ausgelagert<br />
0<br />
1<br />
2<br />
3<br />
4<br />
5<br />
6<br />
7<br />
8<br />
9<br />
10<br />
11<br />
12<br />
13<br />
14<br />
Hauptspeicher<br />
A.0<br />
A.1<br />
A.2<br />
A.3<br />
D.0<br />
D.1<br />
D.2<br />
C.0<br />
C.1<br />
C.2<br />
C.3<br />
D.3<br />
D.4<br />
Prozess D<br />
geladen<br />
Datenstrukturen zum aktuellen Zeitpunkt:<br />
0<br />
1<br />
2<br />
3<br />
0<br />
1<br />
2<br />
3<br />
Seitentabelle<br />
Prozess A<br />
0<br />
1<br />
2<br />
3<br />
7<br />
8<br />
9<br />
10<br />
Seitentabelle<br />
Prozess C<br />
13<br />
14<br />
0<br />
1<br />
2<br />
-<br />
-<br />
-<br />
Seitentabelle<br />
Prozess B<br />
0<br />
1<br />
2<br />
3<br />
4<br />
5<br />
6<br />
11<br />
4 12<br />
Seitentabelle<br />
Prozess D<br />
Liste der freien<br />
Rahmen
Einfaches <strong>Paging</strong><br />
Berechnung von physikalischen Adressen aus logischen<br />
Adressen:<br />
− Voraussetzung: Länge der Seiten ist eine Zweierpotenz<br />
− Logische Adresse besteht aus Seitennummer und Offset.<br />
− Absolute Adresse wird durch Hardware auf Grundlage der<br />
Seitentabelle des Prozesses berechnet.<br />
− …
Einfaches <strong>Paging</strong><br />
Beispiel: logische Adresse der Länge 16 Bit<br />
0 0 0 0 0 1 0 1 1 1 0 1 1 1 1 0<br />
6-Bit-Seitennummer 10-Bit-Offset<br />
− Der Prozess kann somit bis zu 2 6 verschiedene Seiten haben, die über<br />
die Seitentabelle des Prozesses auf Seitenrahmen im Hauptspeicher<br />
abgebildet werden.<br />
− Jede Seite besteht aus 2 10 = 1024 Bytes.<br />
− Berechnung der physikalischen Adresse:
Einfaches <strong>Paging</strong><br />
6-Bit-Seitennummer 10-Bit-Offset<br />
0 0 0 0 0 1 0 1 1 1 0 1 1 1 1 0<br />
= 1<br />
=478<br />
0 1001001<br />
1<br />
1001001 0<br />
2 1101100 1<br />
3 1111101 1<br />
Seitentabelle 0<br />
des Prozesses<br />
Seitenrahmen Nr. 147<br />
(=)<br />
…<br />
…<br />
…<br />
…<br />
Speicherzelle Nr. 478<br />
(= )<br />
innerhalb des<br />
Seitenrahmens.<br />
=> Reale Adresse:<br />
10010011|0111011110
Einfaches <strong>Paging</strong><br />
Entfernen eines Prozesses aus dem Speicher:<br />
− Lagere Prozess auf Hintergrundspeicher aus (z.B. Festplatte).<br />
− Über Seitentabelle kann man feststellen, welche Seitenrahmen dem<br />
Prozess gehören.<br />
− Füge diese Rahmen zur Liste der freien Rahmen hinzu.<br />
− (Keine zusätzlichen Datenstrukturen des Betriebssystems benötigt.)
<strong>Paging</strong> mit virtuellem Speicher<br />
Grundidee:<br />
− Wenn man im Zusammenhang mit Auslagern sowieso mit<br />
Hintergrundspeicher arbeitet, dann hat man auch die Möglichkeit, nur<br />
Teile der Daten von Prozessen ein- bzw. auszulagern.<br />
− Das Programm kann momentan weiter ausgeführt werden, wenn die<br />
aktuell benötigten Informationen (Code und Daten) im Speicher sind.<br />
− Wird auf Informationen zugegriffen, die ausgelagert (auf der<br />
Festplatte) sind, so müssen diese nachgeladen werden.<br />
Bezeichnungen:<br />
− Hauptspeicher = realer Speicher<br />
− Hauptspeicher + Hintergrundspeicher = virtueller Speicher
<strong>Paging</strong> mit virtuellem Speicher<br />
Vorteile:<br />
− Mehr aktive Prozesse im Speicher (=> Pseudoparallelismus!)<br />
− Tatsächlicher Speicherplatzbedarf eines Prozesses muss nicht von<br />
vornherein feststehen.<br />
− Adressraum eines Prozesses kann jetzt größer sein als verfügbarer<br />
Hauptspeicher.<br />
Nachteil:<br />
− Bei Zugriff auf Code/Daten, die nicht im Hauptspeicher vorhanden<br />
sind, muss das Betriebssystem die entsprechenden Seiten<br />
nachladen.<br />
− Dabei müssen evtl. andere Seiten ausgelagert werden, um Platz zu<br />
schaffen.
Lokalität<br />
Kann das überhaupt effizient funktionieren?<br />
− Antwort: meistens!<br />
− Grund: Räumliche und zeitliche Lokalität von Programmen, d.h.<br />
Abarbeitung während kürzerer Zeit bewegt sich häufig in engen<br />
Adressbereichen.<br />
Abarbeitung von Schleifen<br />
In zeitlich engem Abstand Zugriff auf gleiche Daten<br />
Zugriffe auf benachbarte Daten<br />
− => Aufgabe des Programmierers
Lokalität: Beispiel<br />
Matrix mit N x N Elementen.<br />
Arbeitsspeicher „1-dimensional“, daher:<br />
− Ordne jede Zeile nacheinander im Speicher an.<br />
− Zugriff auf Element (i ,j) (i-te Spalte in Zeile j):<br />
j * N + i
Lokalität: Beispiel<br />
Zugriffsmuster Beispiel 1: Initalisiere alle Elemente<br />
− Variante 1<br />
// jede Zeile<br />
for(j = 0; j < N; j++)<br />
{<br />
// jede Spalte<br />
for(i = 0; i < N; i++)<br />
{<br />
pos = j * N + i;<br />
element[pos] = 0;<br />
}<br />
}<br />
Für N = 3000 auf einer aktuellen Intel CPU (IA32): ~0.048 s
Lokalität: Beispiel<br />
Zugriffsmuster Beispiel 1: Initalisiere alle Elemente<br />
− Variante 2: Vertausche Zeilenindex mit Spaltenindex<br />
// jede Spalte<br />
for(j = 0; j < N; j++)<br />
{<br />
// jede Zeile<br />
for(i = 0; i < N; i++)<br />
{<br />
pos = i * N + j;<br />
element[pos] = 0;<br />
}<br />
}<br />
Für N = 3000 auf einer aktuellen Intel CPU (IA32): ~0.160 s
Lokalität: Beispiel<br />
Zugriffsmuster Beispiel 2: Matrixmultiplikation<br />
− Variante 1:<br />
for (i = 0; i < N; ++i)<br />
{<br />
for (j = 0; j < N; ++j)<br />
{<br />
for (k = 0; k < N; ++k)<br />
{<br />
res[i][j] += ma[i][k] * mb[k][j];<br />
}<br />
}<br />
}
Lokalität: Beispiel<br />
Zugriffsmuster Beispiel 2: Matrixmultiplikation<br />
− Variante 2: Transponiere Matrix<br />
// transponiere Matrix B in temporäre Matrix<br />
for (i = 0; i < N; ++i) {<br />
for (j = 0; j < N; ++j) {<br />
tmp[i][j] = mb[j][i];<br />
}<br />
}<br />
for (i = 0; i < N; ++i) {<br />
for (j = 0; j < N; ++j) {<br />
for (k = 0; k < N; ++k) {<br />
res[i][j] += ma[i][k] * tmp[j][k];<br />
}<br />
}<br />
}
Lokalität: Beispiel<br />
Zugriffsmuster Beispiel 2: Matrixmultiplikation<br />
− Test mit N = 1000 (Intel Core Duo 2666 Mhz)<br />
Variante 1: 16.765.297.870 CPU Zyklen<br />
Variante 2: 3.922.373.010 CPU Zyklen<br />
Relativer Gewinn: >70% !!!<br />
− Analyse:<br />
Variante 2 benötigt zusätzlichen Speicher für die transponierte<br />
Matrix. Zudem müssen N*N Elemente kopiert werden.<br />
Dennoch: Die 1000 nicht-sequentiellen Zugriffe (Matrix B) in<br />
Variante 1 sind wesentlich teurer. In Variante 2 kann über beide<br />
Matrizen sequentiell iteriert werden.<br />
− Anmerkung: In diesem Beispiel wirken Cache-Effekte. Die<br />
Datenmenge zu klein, um in den Hintergrundspeicher ausgelagert zu<br />
werden. Dennoch ähnlicher Effekt, da Cache-Speicher um ein<br />
Vielfaches schneller als Hauptspeicher.
Lokalität<br />
<strong>Paging</strong> mit virtuellem Speicher ist nur dann effizient, wenn<br />
Lokalität gegeben.<br />
Falls nicht:<br />
− Ständiges Aus- und Einlagern von Seiten zwischen Hauptspeicher<br />
und Festplatte<br />
− Bezeichnung: Seitenflattern („thrashing“)
Technische Realisierung<br />
Technische Realisierung von <strong>Paging</strong> mit virtuellem Speicher:<br />
− Die Daten des Prozesses befinden sich im Hintergrundspeicher<br />
(Festplatte), bei nicht komplett ausgelagerten Prozessen zusätzlich<br />
noch Teile im Speicher<br />
− Wie bei einfachem <strong>Paging</strong>: Trennung der logischen Adressen in<br />
Seitennummer und Offset, z.B.:<br />
0 0 … 0 1 0 1 1 1 0 0 1 1 1 0<br />
22-Bit-<br />
Seitennummer<br />
− Im Gegensatz zu einfachem <strong>Paging</strong>:<br />
10-Bit-Offset<br />
Logische Adressen überdecken kompletten virtuellen Adressraum, z.B.<br />
32-Bit- / 64-Bit-Adressen<br />
− Pro Prozess eine Seitentabelle zur Übersetzung<br />
Seitennummer => Seitenrahmen
Technische Realisierung<br />
Logische Adresse:<br />
− Seitentabelleneintrag:<br />
0 0 … 0 1 0 1 1 1 0 0 1 1 1 0<br />
22-Bit-<br />
Seitennummer<br />
10-Bit-Offset<br />
P M Weitere Bits Seitenrahmennummer<br />
Present-Bit P: „Seite ist im Hauptspeicher“<br />
Modify-Bit M: „Seite wurde verändert“<br />
Weitere Bits für Schutzrechte und gemeinsame Nutzung<br />
− Seitentabelle liegt im Hauptspeicher<br />
− Umsetzung der virtuellen Adressen in reale Adressen mit<br />
Hardwareunterstützung<br />
(Memory Managment Unit (MMU) des Prozessors)
Adressumsetzung<br />
Virtuelle Adresse<br />
Seitennr. Offset<br />
Register<br />
Seitentabellenzeiger<br />
+<br />
Seitennummer<br />
Seitentabelle<br />
Reale Adresse<br />
Rahmennr. Offset<br />
Rahmennr.<br />
Programm <strong>Paging</strong>-Verfahren Hauptspeicher<br />
Offset<br />
… …<br />
Seitenrahmen
Seitentabelle<br />
Seite 0<br />
Seite 1<br />
Seite 2<br />
Seite 3<br />
Seite 4<br />
Seite 5<br />
Seite 6<br />
Seite 7<br />
virtueller<br />
Adressraum<br />
Seitennr<br />
.<br />
0<br />
1<br />
2<br />
3<br />
4<br />
5<br />
6<br />
7<br />
P<br />
0<br />
0<br />
1<br />
0<br />
1<br />
0<br />
0<br />
0<br />
Seitenrahmen 0<br />
Seitenrahmen 1<br />
Seitenrahmen 2<br />
Seitenrahmen 3<br />
Hauptspeicher<br />
Rahmennr.<br />
Seitentabelle des Prozesses im Hauptspeicher<br />
…<br />
…<br />
…<br />
…<br />
…<br />
…<br />
…<br />
…<br />
…<br />
0<br />
3
Seitenfehler<br />
Was passiert beim Zugriff auf eine Seite, die sich nicht im Hauptspeicher<br />
befindet?<br />
− Hardware (MMU) stellt anhand des present bits fest, dass angefragte Seite<br />
nicht im Hauptspeicher ist (=> „Seitenfehler“ bzw. „page fault“).<br />
− Auslösen einer Unterbrechung („Interrupt“) durch die Hardware<br />
− Behandlung des Interrupts:<br />
Laufendes Programm wird unterbrochen, Sichern des aktuellen Programmzustandes<br />
durch Hardware (Stand des Programmzählers!)<br />
Routine zur Interruptbehandlung wird aufgerufen<br />
− Feststellen des Grundes der Unterbrechung (hier: page fault)<br />
− Behandlung abhängig vom Grund der Unterbrechung, hier:<br />
Betriebssystem lädt die entsprechende Seite von der Festplatte in einen<br />
freien Seitenrahmen<br />
Wenn kein Seitenrahmen frei: Vorheriges Verdrängen eines belegten<br />
Seitenrahmens<br />
Aktualisierung der Seitentabelle<br />
Danach: Laufendes Programm wird wieder fortgesetzt
Seitenfehler<br />
Welche Informationen benötigt das Betriebssystem zum<br />
Einlagern von Seiten (d.h. während der Behandlung einer<br />
Unterbrechung wegen eines page faults)?<br />
− Abbildung Seitennummer --> Festplattenadresse, um die<br />
gesuchte Seite auf der Festplatte zu finden<br />
− Liste freier Seitenrahmen
Seitenfehler<br />
Seite 0<br />
Seite 1<br />
Seite 2<br />
Seite 3<br />
Seite 4<br />
Seite 5<br />
Seite 6<br />
Seite 7<br />
virtueller<br />
Adressraum<br />
Seitennr<br />
.<br />
0<br />
1<br />
2<br />
3<br />
4<br />
5<br />
6<br />
7<br />
P<br />
0<br />
0<br />
1<br />
0<br />
1<br />
0<br />
0<br />
0<br />
Seitenrahmen 0<br />
Seitenrahmen 1<br />
Seitenrahmen 2<br />
Seitenrahmen 3<br />
Hauptspeicher<br />
Rahmennr.<br />
Seitentabelle des Prozesses im Hauptspeicher<br />
…<br />
…<br />
…<br />
…<br />
…<br />
…<br />
…<br />
…<br />
…<br />
0<br />
3<br />
Festplatten-Adresse<br />
A<br />
D<br />
B<br />
X<br />
Y<br />
C<br />
E<br />
F
Verdrängung<br />
Wenn kein freier Seitenrahmen vorhanden: Verdrängen von<br />
Seitenrahmen => Festplatte.<br />
Je nach Betriebssystem:<br />
− Alle Seitenrahmen sind Kandidaten für Verdrängung oder<br />
− Nur Seitenrahmen des eigenen Prozesses<br />
Entscheidung unter diesen Kandidaten gemäß Verdrängungsstrategie<br />
(Ziel: gute Ausnutzung von Lokalität).<br />
Ist das Modify-Bit M gesetzt, dann muss Seite im entsprechenden<br />
Rahmen auf Festplatte zurückgeschreiben werden.<br />
Nach Verdrängen eines Seitenrahmens muss die Seitentabelle des<br />
zugehörigen Prozesses aktualisiert werden.<br />
Da Seitentabellen meist nur dünn besetzt:<br />
− Suchen des verdrängten Seitenrahmens in Seitentabelle des Prozesses<br />
ineffizient<br />
− Abbildung Seitenrahmennummer --> (Prozessnummer, Seitennummer)<br />
hilfreich
Verdrängung<br />
Seite 0<br />
Seite 1<br />
Seite 2<br />
Seite 3<br />
Seite 4<br />
Seite 5<br />
Seite 6<br />
Seite 7<br />
Seite<br />
0<br />
1<br />
2<br />
3<br />
4<br />
5<br />
6<br />
7<br />
P<br />
0<br />
0<br />
1<br />
0<br />
1<br />
0<br />
0<br />
0<br />
…<br />
…<br />
…<br />
…<br />
…<br />
…<br />
…<br />
…<br />
…<br />
Seitentabelle von Prozess 1<br />
Seitenrahmen 0<br />
Seitenrahmen 1<br />
Seitenrahmen 2<br />
Seitenrahmen 3<br />
Rahme<br />
n<br />
0<br />
3<br />
Hauptspeicher<br />
Seite<br />
0<br />
1<br />
2<br />
3<br />
4<br />
5<br />
6<br />
7<br />
Seitenrahmen 2 soll<br />
freigeräumt werden.<br />
P<br />
0<br />
0<br />
1<br />
0<br />
0<br />
0<br />
1<br />
0<br />
…<br />
…<br />
…<br />
…<br />
…<br />
…<br />
…<br />
…<br />
…<br />
Rahme<br />
n<br />
Seitentabelle von Prozess 2<br />
1<br />
2<br />
Seite 0<br />
Seite 1<br />
Seite 2<br />
Seite 3<br />
Seite 4<br />
Seite 5<br />
Seite 6<br />
Seite 7<br />
virtueller<br />
Adressraum<br />
Prozess 2<br />
Seite 6 von<br />
Prozess 2 soll<br />
ausgelagert werten<br />
=> P=0
Verdrängung<br />
Seite 0<br />
Seite 1<br />
Seite 2<br />
Seite 3<br />
Seite 4<br />
Seite 5<br />
Seite 6<br />
Seite 7<br />
Rahmen<br />
0<br />
1<br />
2<br />
3<br />
Seitenrahmen 0<br />
Seitenrahmen 1<br />
Seitenrahmen 2<br />
Seitenrahmen 3<br />
Hauptspeicher<br />
Prozess Seite<br />
1<br />
2<br />
2<br />
1<br />
Abbildung Seitenrahmennummer -> (Prozessnummer, Seitennummer)<br />
2<br />
2<br />
6<br />
4<br />
Seite 0<br />
Seite 1<br />
Seite 2<br />
Seite 3<br />
Seite 4<br />
Seite 5<br />
Seite 6<br />
Seite 7