Die MMU greift auf eine Tabelle zu, die beschreibt, wie virtuelle Adressen in physikalische Adressen übersetzt werden. (Es muss keine physischen Adressen in virtuelle Adressen übersetzen, und dies wäre im Allgemeinen unmöglich, da auf dieselbe physische Adresse über mehrere virtuelle Adressen zugegriffen werden kann oder nicht zugeordnet werden kann.) Das Layout dieser Tabelle hängt von der CPU-Architektur ab. aber das allgemeine Prinzip ist immer dasselbe:Es gibt ein CPU-Register, das die physikalische Adresse einer Tabelle enthält, das die physikalischen Adressen weiterer Tabellen enthält, und so weiter (für insgesamt 2 bis 4 Ebenen bei bestehenden Architekturen) bis zu einer Ebene von Tabellen die die physikalischen Adressen enthält, an denen sich die Daten befinden. Auf jeder Ebene wird durch einige der Bits in der virtuellen Adresse bestimmt, welches Element der Tabelle verwendet werden soll.
Die MMU kennt die Betriebssystemprozesse als solche nicht. Wenn die CPU auf die Ausführung eines anderen Prozesses umschaltet, d. h. wenn ein Kontextwechsel auftritt, ist es die Aufgabe des Kontextumschaltcodes des Betriebssystems, die MMU-Tabellen nach Bedarf zu aktualisieren. In der Praxis denke ich, dass alle Unix-Systeme eine Kopie der Tabellen für jeden Prozess im Speicher behalten und einfach das MMU-Register aktualisieren, um auf die Top-Level-Tabelle für den aktuellen Prozess zu zeigen.
Es gibt tatsächlich einen Teil der MMU, der sich um Betriebssystemprozesse kümmert:der TLB. Das Nachschlagen von Einträgen in der MMU-Tabelle ist ziemlich kostspielig, da es mehrere Speicherzugriffe beinhaltet. Der TLB ist ein Cache dieser Lookups. Bei einem Kontextwechsel muss das Betriebssystem den TLB ungültig machen (d. h. alle Cache-Einträge entfernen), da die Zuordnung für den neuen Prozess anders sein wird. Viele Architekturen ermöglichen es dem Betriebssystem, einen Indikator in jeden MMU-Tabelleneintrag zu setzen, um zu sagen:„Dieser Eintrag gehört zu Prozess N“. Ein TLB-Eintrag wird dann übersprungen, wenn die darin enthaltene Prozessnummer nicht die aktuelle Prozessnummer ist. Ein CPU-Register enthält die aktuelle Prozessnummer und der Kontextumschaltcode aktualisiert sie. Dieser Mechanismus bedeutet, dass der TLB Informationen über mehrere Prozesse gleichzeitig enthalten kann, was die Leistung beim Hin- und Herschalten zwischen diesen Prozessen verbessert. Da zum Speichern von N häufig weniger Bits zur Verfügung stehen, als zum Speichern aller Prozess-IDs des Betriebssystems benötigt werden, ist N nicht die Prozess-ID, sondern eine vom Betriebssystem zu diesem Zweck generierte Zahl, die sich im Laufe der Zeit ändert, sofern sie überhaupt verwendet wird. P>
Unter Linux verwaltet der Kernel eine dreistufige Seitentabelle (unabhängig von den Fähigkeiten der CPU). Die oberste Ebene ist das globale Verzeichnis der Seite, und jeder Prozess hat sein eigenes Verzeichnis, pgd
in mm_struct
. Somit kann jeder Prozess seine eigenen Zuordnungen haben, sodass die Adresse 12345 in verschiedenen Prozessen auf unterschiedliche physikalische Adressen zeigt.
CPUs sind sich der Prozesse nicht wirklich bewusst, aber sie verfügen in der Regel über Funktionen, um sie zu unterstützen. Auf CPUs im x86-Stil gibt es verschiedene aufgabenbezogene Funktionen, die jedoch eher ignoriert werden. Da die Prozessplanung vom Kernel verwaltet wird, kann er Seitentabellenänderungen selbst verfolgen und den CPU-Status aktualisieren, der erforderlich ist, um zur Seitentabelle eines neuen Prozesses zu wechseln, wenn er Aufgaben wechselt. Auf x86-PCs beinhaltet dies die Aktualisierung des CR3-Steuerregisters, das auf das Seitenverzeichnis zeigt.
Das Kapitel „Page Table Management“ in Mel Gormans Understanding the Linux Virtual Memory Manager Buch gibt einen guten Überblick.