[LINUX] Wann wird die mmap (2) -Datei aktualisiert? (1)

Wenn Sie eine Datei mit MAP_SHARED mithilfe von mMap (2), das jeder liebt, dem virtuellen Speicherbereich zuordnen, wird das Schreiben in diesen Speicher in der Datei wiedergegeben. Wann und wer erkennt das Schreiben in diese Erinnerung?

Virtueller Speicher und MMU

In Anbetracht des Mechanismus von mmap (2) und der Funktion der CPU gibt es ungefähr zwei mögliche Mechanismen. Vorher werde ich kurz die Funktionsweise des Betriebssystems und die Funktionen der CPU erläutern.

Eine der wichtigen Aufgaben des Betriebssystems besteht darin, jeder Aufgabe (Prozess in der Unix-Terminologie) einen unabhängigen virtuellen Speicherplatz zuzuweisen. Die Adresse 100 eines Prozesses erhält (sofern nicht anders angegeben) einen anderen physischen Speicher als die Adresse 100 eines anderen Prozesses. Die MMU (Memory Management Unit) ist die Hardware, die den virtuellen Speicherplatz und den physischen Speicherplatz in einer CPU wie einem PC, Server oder Smartphone unter Linux abbildet. Viele moderne CPUs verfügen über eine integrierte MMU, wurden jedoch in der Vergangenheit manchmal extern in der Nähe der CPU angeschlossen. Linux geht von einer MMU vom Typ Paging aus, die den Speicher verwaltet, indem sie ihn in Seiten einer bestimmten Größe unterteilt.

In vielen aktuellen Mainstream-CPUs wie x86_64, ARM und Power beträgt die Seitengröße im Prinzip 4 KB. Da 4 KB 12 Bit sind, kann die 64-Bit-Adresse des virtuellen Speichers durch den Seitenversatz der unteren 12 Bit und die Seitenzahl (virtuelle Seitenzahl) des virtuellen Speicherplatzes der oberen 52 Bit dargestellt werden.

pt.png

Die MMU verwendet eine Tabelle, die als Seitentabelle im Speicher bezeichnet wird, um Seiten im virtuellen Speicher in Seiten im physischen Speicher zu konvertieren. Eine Seitentabelle kann als Array bezeichnet werden, das durch virtuelle Seitenzahlen indiziert ist. In der Realität wird der virtuelle Speicherplatz nur sparsam genutzt, und die Größe der Seitentabelle wird reduziert, indem sie mehrstufig gestaltet wird (4 bis 5 Stufen in x86-64). Außerdem werden in x86-64 nur 48 von 64 Bit verwendet. Jeder x86-64-Seitentabelleneintrag (PTE: Seitentabelleneintrag) hat eine Breite von 64 Bit, mit einer physischen Seitenzahl (PFN: Seitenrahmennummer) auf der Oberseite und verschiedenen Informationen über die Seite auf den unteren 12 Bit in einer Bitmap. Haben. Was in diesem Dokument wichtig ist, sind die Informationen auf der unteren Seite. x86-64 enthält die folgenden Informationen, andere Architekturen (mit unterschiedlichen Namen) enthalten jedoch ähnliche Informationen.

pte.png (Quelle: Intel® 64- und IA-32-Architekturen, Softwareentwicklerhandbuch, Band 3A)

Wenn ein Prozess versucht, auf eine Seite zuzugreifen, auf der ein P-Bit gelöscht wurde, wird das Betriebssystem mit der Ausnahme Seitenfehler (#PF in x86-Terminologie) benachrichtigt. Das Betriebssystem empfängt möglicherweise #PF und schreibt die Seitentabelle entsprechend um, um die Ausführung des Prozesses fortzusetzen, oder es kann einen Fehler als unzulässigen Speicherzugriff verursachen (normalerweise ein Segmentierungsfehlersignal in einem Unix-basierten Betriebssystem). Wenn ein Prozess versucht, auf eine Seite zu schreiben, auf der das R / W-Bit gelöscht ist, wird #PF (Schreibfehler) an das Betriebssystem benachrichtigt, und die Seitentabelle kann entsprechend umgeschrieben und die Prozessausführung fortgesetzt werden. Und es kann ein Fehler sein.

Ein Hauptmerkmal von D und A ist, dass sich die CPU ändern kann. Die CPU ändert nicht die anderen Teile der Seitentabelle, sondern nur das Betriebssystem. Auch wenn die CPU von D und A von 0 auf 1 geändert werden kann, wird sie nicht von 1 auf 0 gelöscht.

Seiten-Cache und Export des Cache

In den meisten Unix-basierten Betriebssystemen wie Linux werden Speicherdaten im Speicher zwischengespeichert, dies erfolgt jedoch seitenweise, sodass sie als Seiten-Cache bezeichnet werden. Die mmap der Datei wird realisiert, indem dieser Seitencache dem virtuellen Speicherplatz zugeordnet wird. Beim normalen Schreiben (2) (einschließlich pwrite (2), writev (2) usw.) wird vor dem Schreiben ein Seitencache erstellt (dh der gesamte Seiteninhalt wird aus dem Speicher gelesen) und dieser Seitencache neu geschrieben. .. Zum Zeitpunkt des Schreibens (2) usw. kann das Betriebssystem feststellen, dass der Seitencache neu geschrieben wurde und die Konsistenz mit dem Original im Speicher verloren gegangen ist. Eine Seite, die nicht mit dem Original übereinstimmt, wird als fehlerhafte Seite bezeichnet. Die fehlerhafte Seite wird jedoch zu einem geeigneten Zeitpunkt in den Speicher geschrieben und hat den gleichen Status wie das Original, dh eine saubere Seite. Unter Linux sind der frühere bdflush, pdflush und der aktuelle bdi flusher für dieses Schreiben verantwortlich, und der Optimierungsparameter vm.dirty_ratio von sysctl, der ein Geheimnis von SIer-Unternehmen geworden ist, usw. ändern das Verhalten dieses bdi flusher. Es ist eine Sache.

Im Fall von mmap wird die Situation schwierig. Der Prozess schreibt ohne Erlaubnis in den Speicher, einschließlich des Bereichs, in dem die Datei zugeordnet ist. Normalerweise weiß das Betriebssystem (Kernel) nicht, wann und wo es geschrieben wurde. In gewisser Weise müssen Sie erkennen, was der Prozess im zugeordneten Bereich geschrieben hat und auf welcher Seite er geschrieben hat, und diese Seite verschmutzen.

Abgesehen davon verwenden einige frühere Implementierungen einen Seiten-Cache für mMap (2), verwenden jedoch einen separaten Puffer-Cache-Mechanismus für Schreiben (2), der zwischen den beiden Caches überflüssig ist. Es gab auch Probleme wie das Kopieren und das Beschädigen von Dateiinhalten, wenn mMap (2) und Write (2) parallel verwendet wurden (bis zu Linux-2.2, NetBSD-1.5 usw.). Derzeit wurde die Verwendung des Seitencaches zum Schreiben (2) usw. verbessert, und ein solches Problem tritt nicht auf.

Erkennung des Schreibens in den mmap-Bereich

Basierend auf der MMU-Funktion, die ich zuvor geschrieben habe, gibt es meiner Meinung nach zwei Möglichkeiten, das Schreiben in den mMap-Bereich zu ergänzen.

  1. Suchen Sie die mit dem D-Bit von PTE und machen Sie es schmutzig. Löschen Sie das D-Bit beim Exportieren in den Speicher. 1a. Scannen und finden Sie alle Seitentabellen (entsprechend dem virtuellen Raum aller Prozesse). 1b. Suchen Sie für jede physische Seite nach dem PTE, der darauf verweist.

  2. Löschen Sie das R / W-Bit, fangen Sie den generierten #PF (Schreibfehler) ab, verschmutzen Sie die Seite und setzen Sie gleichzeitig das R / W-Bit, um den Prozess neu zu starten. Löschen Sie das R / W-Bit, wenn Sie in den Speicher schreiben.

Ich habe bereits einige Nachforschungen an der Seitentabelle angestellt und schaue mir ein bisschen an. Der Seitencache wird freigegeben, wenn er längere Zeit nicht verwendet wird (andernfalls füllt er den Speicher aus), wird jedoch verwendet, um festzustellen, dass er lange Zeit nicht verwendet wurde. Dies wird als [Seitenersetzungsalgorithmus] bezeichnet (https://ja.wikipedia.org/wiki/Page Replacement Algorithm).

Der folgende Algorithmus bestimmt beispielsweise den freizugebenden Cache. Registrieren Sie zunächst alle im Seitencache verwendeten Seiten in der Liste. Als Seitencache neu gesicherte Seiten werden am Ende der Liste hinzugefügt. Wenn Ihnen der freie Speicherplatz ausgeht, durchsuchen Sie diese Liste von Anfang an, um das A-Bit des PTE zu finden, das auf die Seite verweist. Seiten, die gelöscht bleiben, gelten als eine Weile nicht verwendet, daher werden sie freigegeben. Wenn sie jedoch festgelegt sind, werden sie an das Ende der Liste verschoben. Infolgedessen wird die Liste mit Seiten angeordnet, die am Anfang weniger häufig verwendet werden, und Seiten, die am Ende häufig verwendet werden (LRU: Least Recent Used order). Obwohl ich hier über den Seitencache geschrieben habe, können die im Auslagerungsbereich zu speichernden Seiten durch Ausführen derselben Verarbeitung im anonymen Speicher bestimmt werden.

In der Realität ist es üblich, es aus der Liste zu entfernen, es einer anderen Liste mit dem Namen inaktiv hinzuzufügen und eine Weile zu warten. Die zuerst erläuterte Liste wird als aktive Liste bezeichnet, und das Verhältnis von aktiv, inaktiv und frei wird konstant gehalten. Wenn das Obige auf einfache Weise implementiert wird, wird der Scan außerdem stark vorgespannt, so dass eine Vorrichtung zum effizienten und fairen Scannen des Ganzen hergestellt wird. Darüber hinaus gibt es je nach Betriebssystem und Version kleine Unterschiede, z. B. wann und unter welchen Bedingungen der Scan ausgeführt wird, wie viele Seiten verschoben werden, wie stark der Seitencache und der anonyme Speicher gleich oder unterschiedlich behandelt werden. Es gibt, aber die grobe Operation ist so.

Kommen wir zurück zu mmap. Methode 1a (vorläufig als Seitentabellen-Scanmethode bezeichnet) ist eine einfache PTE-Untersuchung. Sie können D-Bit und A-Bit gleichzeitig untersuchen. Bereiche, die aus mehreren virtuellen Bereichen (Executive-Dateien, gemeinsam genutzte Bibliotheken usw.) zugeordnet wurden, werden während einer Runde des gesamten verwendeten Speichers mehrmals untersucht.

Methode 1b (vorübergehend als physische Seitenscanmethode bezeichnet) erfordert eine Methode zum Überprüfen des virtuellen Raums und der virtuellen Adresse, die ihn von der physischen Seite abbildet. Da ein Bit gleichzeitig untersucht werden kann, kann die zuvor erwähnte Aktiv / Inaktiv-Liste verwendet werden, um alle verwendeten physischen Seiten zu verfolgen. Es scheint, dass das Scannen entsprechend der Verwendungshäufigkeit optimiert werden kann.

Unabhängig davon, ob es sich um 1a oder 1b handelt, müssen Sie alle verwendeten Seiten über einen bestimmten Zeitraum untersuchen. Andernfalls sind verschmutzte Seiten für längere Zeit nicht erkennbar. Im Fall von 1a kann jedoch eine Optimierung wie das Überspringen des Scans des virtuellen Raums des Prozesses, der kürzlich nicht geplant wurde, in Zusammenarbeit mit dem Prozessplaner in Betracht gezogen werden.

Bei der zweiten Methode (vorübergehend als Schreibfehlererfassungsmethode bezeichnet) besteht das Problem darin, dass die Verarbeitung von #PF möglicherweise sehr umfangreich ist. Zu viele Schreibfehler können den Prozess verlangsamen. Es ist bekannt, dass in der Nähe des Speichers (Zugriffslokalität) viel Zugriff besteht. Sobald jedoch ein Schreibfehler auftritt und das R / W-Bit gesetzt ist, bleibt die Seite für eine Weile verschmutzt. Durch Löschen des R / W-Bits unmittelbar vor dem Schreiben muss es reduziert werden, indem mehrere Speicherschreibvorgänge gleichzeitig in den Speicher geschrieben werden. Auf der anderen Seite können Sie, da Sie den Moment erfassen können, in dem es schmutzig wird, garantieren, dass es 30 Sekunden nach dem Verschmutzen in den Speicher geschrieben wird (mit dem Schreiben beginnen), oder die Anzahl der schmutzigen Seiten innerhalb eines bestimmten Niveaus halten. Wird einfacher sein.

Dies ist das Ende dieses Artikels, da er lang geworden ist. Als ich tatsächlich den Quellcode des Betriebssystems eines OSS untersuchte, fand ich das Betriebssystem, das tatsächlich die physische Seiten-Scan-Methode von 1b und die Schreibfehler-Erfassungsmethode von 2 verwendet, also [Nächster Artikel]( Ich möchte es unter https://qiita.com/SIGABRT/items/667b24a809f1575a2640 vorstellen.

Recommended Posts

Wann wird die mmap (2) -Datei aktualisiert? (3)
Wann wird die mmap (2) -Datei aktualisiert? (2)
Wann wird die mmap (2) -Datei aktualisiert? (1)
Sagen Sie voraus, wann die ISS sichtbar sein wird
"Temporäre Lösung", wenn pip nicht aktualisiert werden kann [Python]
Seien Sie vorsichtig, wenn Sie mit gzip-komprimierten Textdateien arbeiten
[Python] Wann werden Variablen erstellt? Wann werden Klasseninstanzen gelöscht?
Reverse Pull Numpy / Pandas (wird jederzeit aktualisiert)
Wenn USB nicht formatiert werden konnte
Wenn pydub nicht installiert werden kann