3 Stimmen

Wann wird ein O_SYNC-Schreibvorgang im Pagecache (mmap'd file) sichtbar?

Ich habe eine Datei mmap'd read-only/shared, mit mehreren Threads/Prozesse lesen die Daten gleichzeitig. Ein einzelner Schreiber darf die Daten jederzeit ändern (mit einem Mutex in einem separaten gemeinsamen Speicherbereich). Änderungen werden mit einem write() auf der zugrunde liegenden Datei durchgeführt. Der gesamte Aufbau ist Teil einer Datenbank, die transaktionskonsistent sein soll.

Es wird eine beliebige Anzahl von Datenseiten in beliebiger Reihenfolge ausgegeben, und dann wird fdatasync() aufgerufen. Nichts in der Datei zeigt auf diese geänderten Seiten, bis eine Root-Seite geschrieben wird. Die Root-Seite wird unter Verwendung eines zweiten Dateideskriptors geschrieben, der mit O_SYNC geöffnet wurde, so dass der Schreibvorgang nicht zurückkehrt, bevor die Root-Seite erfolgreich geschrieben wurde. Alle Seiten, die geschrieben werden, sind Teil der mmap-Region, so dass sie schließlich für alle Leser sichtbar werden.

Die Frage ist, ob der endgültige O_SYNC-Schreibvorgang sofort sichtbar wird, sobald der Kernel den Benutzerpuffer in den Seiten-Cache kopiert. Oder wird er erst sichtbar, wenn der synchrone Schreibvorgang abgeschlossen ist? Ich habe den Kernel-Code ein wenig durchgelesen, bin ihm aber nicht ganz gefolgt; für mich sieht es so aus, als ob die Benutzerdaten sofort in den Seiten-Cache kopiert werden, dann wird ein Schreibvorgang geplant, und dann wird gewartet, bis der Schreibvorgang abgeschlossen ist. In der Zwischenzeit befinden sich die geschriebenen Daten bereits im Page Cache und sind somit für die Leseprozesse sofort sichtbar. Dies ist unerwünscht, denn wenn der physische Schreibvorgang fehlschlägt, muss die Transaktion zurückgesetzt werden, und die Leser sollten niemals etwas sehen können, das von einer fehlgeschlagenen Transaktion geschrieben wurde.

Weiß jemand mit Sicherheit, wie O_SYNC-Schreibvorgänge mit dem Seiten-Cache interagieren? Ich nehme an, nur um sicher zu sein, kann ich wrap Zugriffe auf die Root-Seite mit einem Mutex, aber das fügt eine Schicht von Overhead, die besser zu vermeiden wäre.

2voto

caf Punkte 224189

Nach dem formalen POSIX-Standard sind Aktualisierungen von MAP_SHARED Regionen können jederzeit auftreten. Die Definition der synchronisierten E/A legt fest, dass der Schreibvorgang erst dann zurückkehrt, wenn die Daten auf dem physischen Medium angekommen sind, sagt aber nichts über die Daten aus, die von anderen Prozessen gesehen werden.

In der Praxis funktioniert es unter Linux so, wie Sie es beschrieben haben - der Seiten-Cache ist der Bereitstellungsbereich, von dem aus die Schreibvorgänge auf dem Gerät abgewickelt werden, und ein MAP_SHARED Mapping ist eine Ansicht des Seiten-Caches.

Alternativ können Sie eine Kopie der Root-Seite in einen gemeinsamen anonymen Bereich legen. Die lesenden Prozesse würden diese Kopie verwenden, und der schreibende Prozess würde sie aktualisieren, nachdem er die Root-Seite mit der Festplatte synchronisiert hat. Eine Synchronisierung ist jedoch immer noch erforderlich, da man eine ganze Seite nicht atomar aktualisieren kann.

0voto

J-16 SDiZ Punkte 25675

Sie sollten Folgendes verwenden msync(2) für mmapped-Dateien. Die Vermischung von Schreib- und mmapped-Zugriff birgt Probleme in sich.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X