Diese Frage soll das Vakuum guter freier Informationen zu diesem Thema füllen.
Ich glaube, dass eine gute Antwort in eine große SO-Antwort oder zumindest in einige wenige Antworten passt.
Das Hauptziel ist es, vollständigen Anfängern gerade genug Informationen zu geben, damit sie das Handbuch selbst erstellen und grundlegende Betriebssystemkonzepte im Zusammenhang mit Paging verstehen können.
Vorgeschlagene Richtlinien:
- Antworten sollten anfängerfreundlich sein:
- konkrete, aber möglicherweise vereinfachte Beispiele sind sehr wichtig
- Anwendungen der gezeigten Konzepte sind willkommen
- nützliche Ressourcen zu zitieren ist gut
- kleine Einblicke in die Verwendung von Paging-Funktionen durch Betriebssysteme sind willkommen
- PAE- und PSE-Erklärungen sind willkommen
- kleine abschweifungen in x86_64 sind willkommen
Verwandte Fragen und warum ich denke, dass sie keine Betrüger sind:
Wie funktionieren x86-Seitentabellen? : Der Titel ist fast der gleiche wie diese Frage, aber der Körper stellt spezifische Fragen in Bezug auf cr3 und TLB. Diese Frage ist eine Teilmenge dieser Frage.
So funktioniert die x86-Virtualisierung : body fragt nur nach Quellen.
quelle
faq
Tag finden.Antworten:
Version dieser Antwort mit einem schönen Inhaltsverzeichnis und mehr Inhalt .
Ich werde jeden gemeldeten Fehler korrigieren. Wenn Sie große Änderungen vornehmen oder einen fehlenden Aspekt hinzufügen möchten, nehmen Sie diese nach Ihren eigenen Antworten vor, um die wohlverdiente Wiederholung zu erhalten. Kleinere Änderungen können direkt in zusammengeführt werden.
Beispielcode
Minimales Beispiel: https://github.com/cirosantilli/x86-bare-metal-examples/blob/5c672f73884a487414b3e21bd9e579c67cd77621/paging.S
Wie alles andere in der Programmierung besteht die einzige Möglichkeit, dies wirklich zu verstehen, darin, mit minimalen Beispielen zu spielen.
Was dies zu einem "schwierigen" Thema macht, ist, dass das minimale Beispiel groß ist, weil Sie Ihr eigenes kleines Betriebssystem erstellen müssen.
Intel Handbuch
Obwohl es ohne Beispiele nicht zu verstehen ist, versuchen Sie, sich so schnell wie möglich mit den Handbüchern vertraut zu machen.
Intel beschreibt das Paging im Intel Manual Volume 3 System Programming Guide - 325384-056US September 2015, Kapitel 4 "Paging".
Besonders interessant ist Abbildung 4-4 "Formate von CR3- und Paging-Struktur-Einträgen mit 32-Bit-Paging", in der die wichtigsten Datenstrukturen dargestellt sind.
MMU
Das Paging erfolgt durch den MMU-Teil ( Memory Management Unit ) der CPU. Wie viele andere (z. B. x87-Co-Prozessor , APIC ) war dies früher ein separater Chip, der später in die CPU integriert wurde. Aber der Begriff wird immer noch verwendet.
Generelle Fakten
Logische Adressen sind die Speicheradressen, die im "normalen" Benutzerlandcode verwendet werden (z. B. der Inhalt von
rsi
inmov eax, [rsi]
).Die erste Segmentierung übersetzt sie in lineare Adressen, und das Paging übersetzt dann lineare Adressen in physikalische Adressen.
In den meisten Fällen können wir uns physische Adressen als Indizierung der tatsächlichen RAM-Hardwarespeicherzellen vorstellen. Dies ist jedoch nicht zu 100% der Fall, weil:
Paging ist nur im geschützten Modus verfügbar. Die Verwendung von Paging im geschützten Modus ist optional. Paging ist aktiviert, wenn das
PG
Bit descr0
Registers gesetzt ist.Paging gegen Segmentierung
Ein wesentlicher Unterschied zwischen Paging und Segmentierung besteht darin, dass:
Dies ist der Hauptvorteil des Paging, da gleich große Blöcke die Verwaltung vereinfachen.
Paging ist so populär geworden, dass die Unterstützung für die Segmentierung in x86-64 im 64-Bit-Modus, dem Hauptbetriebsmodus für neue Software, eingestellt wurde, wo es nur im Kompatibilitätsmodus existiert, der IA32 emuliert.
Anwendung
Paging wird verwendet, um virtuelle Adressräume von Prozessen in modernen Betriebssystemen zu implementieren. Mit virtuellen Adressen kann das Betriebssystem zwei oder mehr gleichzeitige Prozesse in einem einzelnen RAM so anpassen, dass:
Das Paging erfolgte historisch nach der Segmentierung und ersetzte es weitgehend für die Implementierung des virtuellen Speichers in modernen Betriebssystemen wie Linux, da es einfacher ist, die Speicherblöcke mit fester Größe von Seiten anstelle von Segmenten variabler Länge zu verwalten.
Hardware-Implementierung
Wie die Segmentierung im geschützten Modus (bei der das Ändern eines Segmentregisters eine Last von GDT oder LDT auslöst) verwendet die Paging-Hardware Datenstrukturen im Speicher, um ihre Arbeit zu erledigen (Seitentabellen, Seitenverzeichnisse usw.).
Das Format dieser Datenstrukturen wird von der Hardware festgelegt . Es ist jedoch Sache des Betriebssystems, diese Datenstrukturen im RAM korrekt einzurichten und zu verwalten und der Hardware mitzuteilen, wo sie zu finden sind (via
cr3
).Einige andere Architekturen überlassen das Paging fast vollständig der Software, sodass ein TLB-Fehler eine vom Betriebssystem bereitgestellte Funktion ausführt, um die Seitentabellen zu durchsuchen und die neue Zuordnung in den TLB einzufügen. Dadurch müssen die Seitentabellenformate vom Betriebssystem ausgewählt werden, es ist jedoch unwahrscheinlich, dass die Hardware Seitenläufe mit der Ausführung anderer Anweisungen in nicht ordnungsgemäßer Reihenfolge überlappen kann, wie dies bei x86 möglich ist .
Beispiel: vereinfachtes einstufiges Paging-Schema
Dies ist ein Beispiel dafür, wie Paging auf einer vereinfachten Version der x86-Architektur ausgeführt wird, um einen virtuellen Speicherbereich zu implementieren.
Seitentabellen
Das Betriebssystem könnte ihnen die folgenden Seitentabellen geben:
Seitentabelle, die vom Betriebssystem an Prozess 1 übergeben wurde:
Seitentabelle, die vom Betriebssystem an Prozess 2 übergeben wurde:
Wo:
PT1
undPT2
: Anfangsposition von Tabelle 1 und 2 im RAM.Beispielwerte:
0x00000000
,0x12345678
usw.Es ist das Betriebssystem, das diese Werte entscheidet.
L
: Länge eines Seitentabelleneintrags.present
: Zeigt an, dass die Seite im Speicher vorhanden ist.Seitentabellen befinden sich im RAM. Sie könnten zum Beispiel wie folgt lokalisiert sein:
Die anfänglichen Speicherorte im RAM für beide Seitentabellen sind beliebig und werden vom Betriebssystem gesteuert. Es ist Sache des Betriebssystems, sicherzustellen, dass sie sich nicht überschneiden!
Jeder Prozess kann keine Seitentabellen direkt berühren, obwohl er Anforderungen an das Betriebssystem stellen kann, die dazu führen, dass die Seitentabellen geändert werden, z. B. nach größeren Stapel- oder Heap-Segmenten.
Eine Seite ist ein Block von 4 KB (12 Bit), und da Adressen 32 Bit haben, sind nur 20 Bit (20 + 12 = 32, also 5 Zeichen in hexadezimaler Schreibweise) erforderlich, um jede Seite zu identifizieren. Dieser Wert wird von der Hardware festgelegt.
Seitentabelleneinträge
Eine Seitentabelle ist ... eine Tabelle mit Seitentabelleneinträgen!
Das genaue Format der Tabelleneinträge wird von der Hardware festgelegt .
In diesem vereinfachten Beispiel enthalten die Seitentabelleneinträge nur zwei Felder:
In diesem Beispiel hätten die Hardware-Designer wählen können
L = 21
.Die meisten realen Seitentabelleneinträge haben andere Felder.
Es wäre unpraktisch, Dinge auf 21 Bit auszurichten, da der Speicher durch Bytes und nicht durch Bits adressierbar ist. Selbst wenn in diesem Fall nur 21 Bit benötigt werden, würden Hardware-Designer wahrscheinlich
L = 32
den Zugriff beschleunigen und nur die verbleibenden Bits für die spätere Verwendung reservieren. Der tatsächliche Wert fürL
x86 beträgt 32 Bit.Adressübersetzung im einstufigen Schema
Sobald die Seitentabellen vom Betriebssystem eingerichtet wurden, wird die Adressumsetzung zwischen linearen und physischen Adressen von der Hardware durchgeführt .
Wenn das Betriebssystem Prozess 1 aktivieren möchte, setzt
cr3
esPT1
den Anfang der Tabelle für Prozess 1 auf.Wenn Prozess 1 auf eine lineare Adresse zugreifen möchte
0x00000001
, führt die Paging- Hardwareschaltung für das Betriebssystem automatisch die folgenden Schritte aus:Teilen Sie die lineare Adresse in zwei Teile:
In diesem Fall hätten wir also:
Schauen Sie in die Seitentabelle 1, weil sie darauf
cr3
verweist.Eintrag suchen,
0x00000
da dies der Seitenteil ist.Die Hardware weiß, dass sich dieser Eintrag an der RAM-Adresse befindet
PT1 + 0 * L = PT1
.da es vorhanden ist, ist der Zugriff gültig
von der Seitentabelle, die Lage der Seitenzahl
0x00000
ist0x00001 * 4K = 0x00001000
.Um die endgültige physikalische Adresse zu finden, müssen wir nur den Offset hinzufügen:
denn
00001
ist die physikalische Adresse der Seite in der Tabelle nachgeschlagen und001
ist der Versatz.Wie der Name schon sagt, wird dem Offset immer einfach die physische Adresse der Seite hinzugefügt.
Die Hardware erhält dann den Speicher an diesem physischen Ort.
Auf die gleiche Weise würden die folgenden Übersetzungen für Prozess 1 erfolgen:
Wenn Sie beispielsweise auf die Adresse zugreifen
00001000
,00001
weiß die Hardware, dass sich der Seitentabelleneintrag an der RAM-Adresse befindet:PT1 + 1 * L
(1
aufgrund des Seitenteils), und dort wird danach gesucht.Wenn das Betriebssystem zu Prozess 2 wechseln möchte, muss es nur
cr3
auf Seite 2 verweisen. So einfach ist das!Nun würden die folgenden Übersetzungen für Prozess 2 passieren:
Dieselbe lineare Adresse wird für verschiedene Prozesse in unterschiedliche physikalische Adressen übersetzt , abhängig nur vom Wert im Inneren
cr3
.Auf diese Weise kann jedes Programm erwarten, dass seine Daten beginnen
0
und endenFFFFFFFF
, ohne sich um genaue physikalische Adressen kümmern zu müssen.Seitenfehler
Was passiert, wenn Prozess 1 versucht, auf eine Adresse innerhalb einer Seite zuzugreifen, die nicht vorhanden ist?
Die Hardware benachrichtigt die Software über eine Seitenfehlerausnahme.
In der Regel muss dann das Betriebssystem einen Ausnahmebehandler registrieren, um zu entscheiden, was zu tun ist.
Es ist möglich, dass der Zugriff auf eine Seite, die sich nicht in der Tabelle befindet, ein Programmierfehler ist:
Es kann jedoch Fälle geben, in denen dies akzeptabel ist, z. B. unter Linux, wenn:
Das Programm möchte seinen Stack erhöhen.
Es wird lediglich versucht, auf ein bestimmtes Byte in einem bestimmten möglichen Bereich zuzugreifen. Wenn das Betriebssystem zufrieden ist, wird diese Seite dem Prozessadressraum hinzugefügt.
Die Seite wurde auf die Festplatte ausgetauscht.
Das Betriebssystem muss einige Arbeiten hinter den Prozessen ausführen, um die Seite wieder in den RAM zu bringen.
Das Betriebssystem kann anhand des Inhalts des restlichen Seitentabelleneintrags feststellen, dass dies der Fall ist, da die anderen Einträge des Seitentabelleneintrags dem Betriebssystem vollständig überlassen bleiben, was es möchte.
Unter Linux zum Beispiel, wenn vorhanden = 0:
Wenn alle Felder des Seitentabelleneintrags 0 sind, ist die Adresse ungültig.
Andernfalls wurde die Seite auf die Festplatte ausgetauscht, und die tatsächlichen Werte dieser Felder codieren die Position der Seite auf der Festplatte.
In jedem Fall muss das Betriebssystem wissen, welche Adresse den Seitenfehler generiert hat, um das Problem beheben zu können. Aus diesem Grund setzen die netten IA32-Entwickler den Wert
cr2
auf diese Adresse, wenn ein Seitenfehler auftritt. Der Ausnahmebehandler kann dann einfach nachsehencr2
, um die Adresse zu erhalten.Vereinfachungen
Vereinfachungen der Realität, die das Verständnis dieses Beispiels erleichtern:
Alle realen Paging-Schaltkreise verwenden mehrstufiges Paging, um Platz zu sparen. Dies zeigte jedoch ein einfaches einstufiges Schema.
Seitentabellen enthielten nur zwei Felder: eine 20-Bit-Adresse und ein 1-Bit-Present-Flag.
Reale Seitentabellen enthalten insgesamt 12 Felder und daher andere Funktionen, die weggelassen wurden.
Beispiel: Mehrstufiges Paging-Schema
Das Problem bei einem einstufigen Paging-Schema besteht darin, dass es zu viel RAM beanspruchen würde: 4G / 4K = 1M Einträge pro Prozess. Wenn jeder Eintrag 4 Byte lang ist, würde dies 4 MB pro Prozess ergeben , was selbst für einen Desktop-Computer zu viel ist:
ps -A | wc -l
sagt, dass ich gerade 244 Prozesse ausführe, was ungefähr 1 GB RAM beanspruchen würde!Aus diesem Grund haben sich x86-Entwickler für ein mehrstufiges Schema entschieden, das die RAM-Nutzung reduziert.
Der Nachteil dieses Systems ist, dass es eine etwas höhere Zugriffszeit hat.
In dem einfachen 3-Ebenen-Paging-Schema, das für 32-Bit-Prozessoren ohne PAE verwendet wird, sind die 32 Adressbits wie folgt unterteilt:
Jedem Prozess muss ein und nur ein Seitenverzeichnis zugeordnet sein, sodass mindestens
2^10 = 1K
Seitenverzeichniseinträge enthalten sind , was viel besser ist als die Mindestanzahl von 1 Million, die für ein einstufiges Schema erforderlich ist.Seitentabellen werden nur nach Bedarf vom Betriebssystem zugewiesen. Jede Seitentabelle enthält
2^10 = 1K
SeitenverzeichniseinträgeSeitenverzeichnisse enthalten ... Seitenverzeichniseinträge! Seitenverzeichniseinträge sind dieselben wie Seitentabelleneinträge, außer dass sie auf RAM-Adressen von Seitentabellen anstelle von physischen Adressen von Tabellen verweisen . Da diese Adressen nur 20 Bit breit sind, müssen sich Seitentabellen am Anfang von 4-KB-Seiten befinden.
cr3
zeigt jetzt auf den Speicherort im RAM des Seitenverzeichnisses des aktuellen Prozesses anstelle von Seitentabellen.Seitentabelleneinträge ändern sich in einem einstufigen Schema überhaupt nicht.
Seitentabellen ändern sich von einem einstufigen Schema, weil:
Der Grund für die Verwendung von 10 Bit auf den ersten beiden Ebenen (und beispielsweise nicht
12 | 8 | 12
) besteht darin, dass jeder Seitentabelleneintrag 4 Byte lang ist. Dann passen die 2 ^ 10 Einträge von Seitenverzeichnissen und Seitentabellen gut in 4-KB-Seiten. Dies bedeutet, dass das Zuweisen und Freigeben von Seiten für diesen Zweck schneller und einfacher ist.Adressübersetzung im mehrstufigen Schema
Seitenverzeichnis, das vom Betriebssystem an Prozess 1 übergeben wurde:
Seitentabellen, die vom Betriebssystem für Prozess 1 unter
PT1 = 0x10000000
(0x10000
* 4K) angegeben wurden:Seitentabellen, die vom Betriebssystem für Prozess 1 unter
PT2 = 0x80000000
(0x80000
* 4K) angegeben wurden:wo:
PD1
: Anfangsposition des Seitenverzeichnisses von Prozess 1 im RAM.PT1
undPT2
: Anfangsposition von Seitentabelle 1 und Seitentabelle 2 für Prozess 1 im RAM.In diesem Beispiel könnten das Seitenverzeichnis und die Seitentabelle im RAM wie folgt gespeichert werden:
Lassen Sie uns die lineare Adresse
0x00801004
Schritt für Schritt übersetzen.Wir nehmen an
cr3 = PD1
, dass es auf das gerade beschriebene Seitenverzeichnis verweist.In binär ist die lineare Adresse:
Gruppierung wie
10 | 10 | 12
folgt:was gibt:
Die Hardware sucht also nach Eintrag 2 des Seitenverzeichnisses.
Die Seitenverzeichnis-Tabelle gibt an, dass sich die Seitentabelle unter befindet
0x80000 * 4K = 0x80000000
. Dies ist der erste RAM-Zugriff des Prozesses.Da es sich bei dem Seitentabelleneintrag um handelt
0x1
, prüft die Hardware den Eintrag 1 der Seitentabelle unter0x80000000
, der angibt, dass sich die physische Seite unter der Adresse befindet0x0000C * 4K = 0x0000C000
. Dies ist der zweite RAM-Zugriff des Prozesses.Schließlich fügt die Paging-Hardware den Offset hinzu, und die endgültige Adresse lautet
0x0000C004
.Andere Beispiele für übersetzte Adressen sind:
Seitenfehler treten auf, wenn entweder ein Seitenverzeichniseintrag oder ein Seitentabelleneintrag nicht vorhanden ist.
Wenn das Betriebssystem einen anderen Prozess gleichzeitig ausführen möchte, gibt es dem zweiten Prozess ein separates Seitenverzeichnis und verknüpft dieses Verzeichnis mit separaten Seitentabellen.
64-Bit-Architekturen
64 Bit sind immer noch zu viel Adresse für aktuelle RAM-Größen, sodass die meisten Architekturen weniger Bit verwenden.
x86_64 verwendet 48 Bit (256 TiB), und die PAE des Legacy-Modus erlaubt bereits 52-Bit-Adressen (4 PiB).
12 dieser 48 Bits sind bereits für den Offset reserviert, wodurch 36 Bits übrig bleiben.
Wenn ein 2-Ebenen-Ansatz gewählt wird, wäre die beste Aufteilung zwei 18-Bit-Ebenen.
Dies würde jedoch bedeuten, dass das Seitenverzeichnis
2^18 = 256K
Einträge enthält, die zu viel RAM benötigen: in der Nähe eines einstufigen Paging für 32-Bit-Architekturen!Daher erstellen 64-Bit-Architekturen noch weitere Seitenebenen, üblicherweise 3 oder 4.
x86_64 verwendet 4 Ebenen in einem
9 | 9 | 9 | 12
Schema, sodass die obere Ebene nur2^9
Einträge höherer Ebene aufnimmt .PAE
Physische Adresserweiterung.
Mit 32 Bit können nur 4 GB RAM adressiert werden.
Dies wurde zu einer Einschränkung für große Server, daher führte Intel den PAE-Mechanismus in Pentium Pro ein.
Um das Problem zu beheben, fügte Intel 4 neue Adressleitungen hinzu, sodass 64 GB adressiert werden konnten.
Die Seitentabellenstruktur wird auch geändert, wenn PAE aktiviert ist. Die genaue Art und Weise der Änderung hängt davon ab, ob die PSE ein- oder ausgeschaltet ist.
PAE wird über das
PAE
Bit von ein- und ausgeschaltetcr4
.Selbst wenn der gesamte adressierbare Speicher 64 GB beträgt, können einzelne Prozesse nur bis zu 4 GB verwenden. Das Betriebssystem kann jedoch unterschiedliche Prozesse auf unterschiedliche 4-GB-Blöcke übertragen.
PSE
Seitengrößenerweiterung.
Ermöglicht Seiten mit einer Länge von 4 MB (oder 2 MB, wenn PAE aktiviert ist) anstelle von 4 KB.
PSE wird über das
PAE
Bit von ein- und ausgeschaltetcr4
.PAE- und PSE-Seitentabellenschemata
Wenn entweder PAE oder PSE aktiv sind, werden verschiedene Paging-Level-Schemata verwendet:
keine PAE und keine PSE:
10 | 10 | 12
keine PAE und PSE :
10 | 22
.22 ist der Versatz innerhalb der 4-MB-Seite, da 22-Bit-Adresse 4 MB ist.
PAE und keine PSE:
2 | 9 | 9 | 12
Der Entwurfsgrund, warum 9 zweimal anstelle von 10 verwendet wird, besteht darin, dass Einträge jetzt nicht mehr in 32 Bits passen, die alle mit 20 Adressbits und 12 aussagekräftigen oder reservierten Flag-Bits gefüllt waren.
Der Grund dafür ist, dass 20 Bit nicht mehr ausreichen, um die Adresse von Seitentabellen darzustellen: 24 Bit werden jetzt benötigt, da dem Prozessor 4 zusätzliche Drähte hinzugefügt wurden.
Aus diesem Grund haben die Designer beschlossen, die Eintragsgröße auf 64 Bit zu erhöhen. Um sie in eine einzelne Seitentabelle einzufügen, muss die Anzahl der Einträge auf 2 ^ 9 anstatt auf 2 ^ 10 reduziert werden.
Die Start-2 ist eine neue Seitenebene namens Page Directory Pointer Table (PDPT), da sie auf Seitenverzeichnisse verweist und die lineare 32-Bit-Adresse ausfüllt. PDPTs sind ebenfalls 64 Bit breit.
cr3
zeigt jetzt auf PDPTs, die sich auf den ersten vier 4 GB Speicher befinden und auf 32-Bit-Vielfachen ausgerichtet sein müssen, um die Adressierungseffizienz zu gewährleisten. Dies bedeutet, dass jetztcr3
27 signifikante Bits anstelle von 20: 2 ^ 5 für die 32 Vielfachen * 2 ^ 27 vorhanden sind, um die 2 ^ 32 der ersten 4 GB zu vervollständigen.PAE und PSE:
2 | 9 | 21
Die Designer haben beschlossen, ein 9 Bit breites Feld beizubehalten, damit es auf eine einzelne Seite passt.
Dies lässt 23 Bits übrig. Wenn Sie 2 für die PDPT belassen, um die Dinge mit dem PAE-Fall ohne PSE einheitlich zu halten, bleibt 21 für den Versatz übrig, was bedeutet, dass die Seiten 2M breit sind anstatt 4M.
TLB
Der Translation Lookahead Buffer (TLB) ist ein Cache für Paging-Adressen.
Da es sich um einen Cache handelt, werden viele Entwurfsprobleme des CPU-Cache gemeinsam genutzt, z. B. die Assoziativitätsstufe.
In diesem Abschnitt wird ein vereinfachter, vollständig assoziativer TLB mit 4 einzelnen Adresseinträgen beschrieben. Beachten Sie, dass echte TLBs wie andere Caches normalerweise nicht vollständig assoziativ sind.
Grundbetrieb
Nachdem eine Übersetzung zwischen linearer und physikalischer Adresse erfolgt ist, wird diese im TLB gespeichert. Ein TLB mit 4 Einträgen startet beispielsweise im folgenden Status:
Das
>
gibt den aktuellen Eintrag an, der ersetzt werden soll.und nachdem eine lineare Seitenadresse
00003
in eine physikalische Adresse übersetzt wurde00005
, wird der TLB:und nach einer zweiten Übersetzung des
00007
auf00009
sie zu:Wenn
00003
nun erneut übersetzt werden muss, sucht die Hardware zuerst den TLB und ermittelt seine Adresse mit einem einzigen RAM-Zugriff00003 --> 00005
.Ist natürlich
00000
nicht im TLB, da kein gültiger Eintrag00000
als Schlüssel enthält .Ersatzrichtlinie
Wenn der TLB voll ist, werden ältere Adressen überschrieben. Genau wie beim CPU-Cache ist die Ersetzungsrichtlinie eine potenziell komplexe Operation, aber eine einfache und vernünftige Heuristik besteht darin, den zuletzt verwendeten Eintrag (LRU) zu entfernen.
Mit LRU ausgehend vom Status:
Hinzufügen
0000D -> 0000A
würde geben:NOCKEN
Die Verwendung des TLB beschleunigt die Übersetzung, da für die anfängliche Übersetzung ein Zugriff pro TLB-Ebene erforderlich ist. Dies bedeutet 2 bei einem einfachen 32-Bit-Schema, 3 oder 4 bei 64-Bit-Architekturen.
Der TLB wird normalerweise als teurer RAM-Typ implementiert, der als Content-Addressable Memory (CAM) bezeichnet wird. CAM implementiert eine assoziative Zuordnung auf Hardware, dh eine Struktur, die mit einem Schlüssel (lineare Adresse) einen Wert abruft.
Zuordnungen könnten auch für RAM-Adressen implementiert werden, aber für CAM-Zuordnungen sind möglicherweise viel weniger Einträge erforderlich als für eine RAM-Zuordnung.
Zum Beispiel eine Karte, in der:
könnte in einem TLB mit 4 Einträgen gespeichert werden:
Um dies jedoch mit RAM zu implementieren, müssten 2 ^ 20 Adressen vorhanden sein :
Das wäre sogar noch teurer als die Verwendung eines TLB.
Einträge ungültig machen
Bei
cr3
Änderungen werden alle TLB-Einträge ungültig, da eine neue Seitentabelle für einen neuen Prozess verwendet wird. Daher ist es unwahrscheinlich, dass einer der alten Einträge eine Bedeutung hat.Der x86 bietet auch die
invlpg
Anweisung, die einen einzelnen TLB-Eintrag explizit ungültig macht. Andere Architekturen bieten noch mehr Anweisungen für ungültig gemachte TLB-Einträge, z. B. die Ungültigmachung aller Einträge in einem bestimmten Bereich.Einige x86-CPUs gehen über die Anforderungen der x86-Spezifikation hinaus und bieten mehr Kohärenz als garantiert, zwischen dem Ändern eines Seitentabelleneintrags und seiner Verwendung, wenn er nicht bereits im TLB zwischengespeichert wurde . Anscheinend hat sich Windows 9x aus Gründen der Korrektheit darauf verlassen, aber moderne AMD-CPUs bieten keine kohärenten Seitengänge. Intel-CPUs tun dies, obwohl sie dafür falsche Spekulationen erkennen müssen. Dies auszunutzen ist wahrscheinlich eine schlechte Idee, da es wahrscheinlich nicht viel zu gewinnen gibt und ein großes Risiko besteht, subtile zeitkritische Probleme zu verursachen, die schwer zu debuggen sind.
Verwendung des Linux-Kernels
Der Linux-Kernel nutzt die Paging-Funktionen von x86 in großem Umfang, um schnelle Prozesswechsel mit geringer Datenfragmentierung zu ermöglichen.
In
v4.2
, Blick unterarch/x86/
:include/asm/pgtable*
include/asm/page*
mm/pgtable*
mm/page*
Es scheinen keine Strukturen definiert zu sein, die die Seiten darstellen, nur Makros:
include/asm/page_types.h
ist besonders interessant. Auszug:arch/x86/include/uapi/asm/processor-flags.h
definiertCR0
und insbesondere diePG
Bitposition:Literaturverzeichnis
Frei:
rutgers-pxk-416 Kapitel "Speicherverwaltung: Vorlesungsunterlagen"
Gute historische Übersicht über Speicherorganisationstechniken, die von älteren Betriebssystemen verwendet werden.
Nicht frei:
bovet05 Kapitel "Speicheradressierung"
Angemessene Einführung in die x86-Speicheradressierung. Es fehlen einige gute und einfache Beispiele.
quelle
real TLBs are not usually fully associative
…The TLB is usually implemented as … CAM
Sind diese beiden Aussagen nicht widersprüchlich?Hier ist eine sehr kurze Antwort auf hoher Ebene:
Ein x86-Prozessor arbeitet in einem von mehreren möglichen Modi (ungefähr: real, geschützt, 64-Bit). Jeder Modus kann eines von mehreren möglichen Speicheradressierungsmodellen verwenden (aber nicht jeder Modus kann jedes Modell verwenden), nämlich: Realmodusadressierung, segmentierte Adressierung und flachlineare Adressierung.
In der modernen Welt ist nur die flachlineare Adressierung im geschützten oder 64-Bit-Modus relevant, und die beiden Modi sind im Wesentlichen gleich, wobei der Hauptunterschied in der Größe des Maschinenworts und damit in der adressierbaren Speichermenge besteht.
Der Speicheradressierungsmodus gibt nun den Speicheroperanden der Maschinenbefehle eine Bedeutung (z. B.
mov DWORD PTR [eax], 25
die eine 32-Bit-Ganzzahl (auch bekannt alsdword
) des Werts 25 in dem Speicher speichert, dessen Adresse imeax
32-Bit-Register gespeichert ist). Bei der flachlinearen Adressierungeax
darf diese Zahl in einem einzelnen zusammenhängenden Bereich von Null bis zum Maximalwert (in unserem Fall 2 32 - 1) laufen .Die flachlineare Adressierung kann jedoch entweder ausgelagert oder nicht ausgelagert werden . Ohne Paging bezieht sich die Adresse direkt auf den physischen Speicher. Beim Paging speist die Speicherverwaltungseinheit (oder MMU) des Prozessors die gewünschte Adresse (jetzt als virtuelle Adresse bezeichnet ) transparent in einen Suchmechanismus, die sogenannten Seitentabellen , ein und erhält einen neuen Wert, der als physikalische Adresse interpretiert wird. Die ursprüngliche Operation verarbeitet jetzt diese neue, übersetzte Adresse im physischen Speicher, obwohl der Benutzer immer nur die virtuelle Adresse sieht.
Der Hauptvorteil von Paging besteht darin, dass die Seitentabellen vom Betriebssystem verwaltet werden. Somit kann das Betriebssystem die Seitentabellen beliebig ändern und ersetzen, beispielsweise beim "Wechseln von Aufgaben". Es kann eine ganze Sammlung von Seitentabellen speichern, eine für jeden "Prozess", und wenn es entscheidet, dass ein bestimmter Prozess auf einer bestimmten CPU ausgeführt wird, lädt es die Seitentabellen des Prozesses in die MMU dieser CPU (jede CPU hat ihre eigene Satz von Seitentabellen). Das Ergebnis ist, dass jeder Prozess seinen eigenen virtuellen Adressraum sieht, der gleich aussieht, unabhängig davon, welche physischen Seiten frei waren, als das Betriebssystem Speicher dafür zuweisen musste. Es kennt nie den Speicher eines anderen Prozesses, da es nicht direkt auf den physischen Speicher zugreifen kann.
Seitentabellen sind verschachtelte baumartige Datenstrukturen, die im normalen Speicher gespeichert sind, vom Betriebssystem geschrieben, aber direkt von der Hardware gelesen werden, sodass das Format festgelegt ist. Sie werden in die MMU "geladen", indem ein spezielles CPU-Steuerregister so eingestellt wird, dass es auf die Tabelle der obersten Ebene verweist. Die CPU verwendet einen Cache, der als TLB bezeichnet wird, um sich Suchvorgänge zu merken. Daher sind wiederholte Zugriffe auf dieselben wenigen Seiten aus TLB-Miss-Gründen sowie aus den üblichen Gründen des Datencaches viel schneller als verstreute Zugriffe. Der Begriff "TLB-Eintrag" bezieht sich häufig auf Seitentabelleneinträge, auch wenn diese nicht im TLB zwischengespeichert sind.
Und falls Sie befürchten, dass ein Prozess möglicherweise nur das Paging deaktiviert oder versucht, die Seitentabellen zu ändern: Dies ist nicht zulässig, da x86 Berechtigungsstufen (sogenannte "Ringe") implementiert und Benutzercode auf einer Berechtigungsstufe ausgeführt wird, die zu niedrig ist, um sie zuzulassen es, um die Seitentabellen der CPU zu ändern.
quelle