Ich weiß, dass eine Seiten-Cache-Seite, wenn sie geändert wird, als verschmutzt markiert ist und ein Zurückschreiben erfordert, aber was passiert, wenn:
Szenario: Die Datei / apps / EXE, bei der es sich um eine ausführbare Datei handelt, wird vollständig im Seiten-Cache abgelegt (alle Seiten befinden sich im Cache / Speicher) und von Prozess P ausgeführt
Die fortlaufende Veröffentlichung ersetzt dann / apps / EXE durch eine brandneue ausführbare Datei.
Annahme 1: Ich gehe davon aus, dass der Prozess P (und jeder andere mit einem Dateideskriptor, der auf die alte ausführbare Datei verweist) weiterhin den alten, im Speicher / in Apps / in der EXE-Datei ohne Probleme verwendet und dass jeder neue Prozess, der versucht, diesen Pfad auszuführen, diesen Pfad erhält die neue ausführbare Datei.
Annahme 2: Ich gehe davon aus, dass, wenn nicht alle Seiten der Datei in den Speicher gemappt sind, die Dinge in Ordnung sind, bis ein Seitenfehler vorliegt, der Seiten aus der Datei erfordert, die ersetzt wurden, und wahrscheinlich ein Fehler auftritt.
Frage 1: Wenn Sie alle Seiten der Datei mit so etwas wie vmtouch blockieren, ändert sich dadurch das Szenario überhaupt?
Frage 2: Wenn sich / apps / EXE auf einem entfernten NFS befindet, würde das einen Unterschied machen? (Nehme ich nicht an)
Bitte korrigieren oder validieren Sie meine 2 Annahmen und beantworten Sie meine 2 Fragen.
Nehmen wir an, dies ist eine CentOS 7.6-Box mit einer Art 3.10.0-957.el7-Kernel
Update: Wenn ich weiter darüber nachdenke, frage ich mich, ob dieses Szenario nicht anders ist als jedes andere Dirty-Page-Szenario.
Ich nehme an, dass der Prozess, der die neue Binärdatei schreibt, einen Lesevorgang durchführt und alle Cache-Seiten abruft, da alle Seiten ausgelagert sind, und dann alle diese Seiten als verschmutzt markiert werden. Wenn sie gesperrt sind, handelt es sich nur um nutzlose Seiten, die den Hauptspeicher belegen, nachdem die Referenzanzahl auf Null gesetzt wurde.
Ich vermute, wenn die aktuell ausgeführten Programme enden, wird alles andere die neue Binärdatei verwenden. Vorausgesetzt, dass alles in Ordnung ist, denke ich, dass es nur interessant ist, wenn nur ein Teil der Datei ausgelagert wird.
quelle
Antworten:
Dies ist der wichtige Teil.
Die Art und Weise, wie eine neue Datei veröffentlicht wird, besteht darin, eine neue Datei zu erstellen (z. B.
/apps/EXE.tmp.20190907080000
), den Inhalt zu schreiben, Berechtigungen und Eigentumsrechte festzulegen und sie schließlich in den endgültigen Namen umzubenennen (2)/apps/EXE
und die alte Datei zu ersetzen.Das Ergebnis ist, dass die neue Datei eine neue Inode-Nummer hat (was praktisch bedeutet, dass es sich um eine andere Datei handelt).
Und die alte Datei hatte eine eigene Inode-Nummer, die eigentlich immer noch existiert, obwohl der Dateiname nicht mehr darauf verweist (oder es gibt keine Dateinamen mehr, die auf diese Inode verweisen).
Der Schlüssel hier ist also, dass wenn wir unter Linux von "Dateien" sprechen, wir meistens wirklich von "Inodes" sprechen, da nach dem Öffnen einer Datei der Inode der Verweis ist, den wir auf die Datei behalten.
Richtig.
Falsch. Der alte Inode ist noch vorhanden, sodass Seitenfehler aus dem Prozess, der die alte Binärdatei verwendet, diese Seiten weiterhin auf der Festplatte finden können.
Sie können einige Auswirkungen davon feststellen, indem Sie sich den
/proc/${pid}/exe
Symlink (oder die entsprechendelsof
Ausgabe) für den Prozess ansehen, in dem die alte Binärdatei ausgeführt wird. Dieser zeigt/app/EXE (deleted)
an, dass der Name nicht mehr vorhanden ist, der Inode jedoch noch vorhanden ist.Sie können auch sehen, dass der von der Binärdatei verwendete Speicherplatz erst freigegeben wird, nachdem der Prozess beendet wurde (vorausgesetzt, es ist der einzige Prozess, bei dem dieser Inode geöffnet ist.) Überprüfen Sie die Ausgabe von
df
vor und nach dem Beenden des Prozesses, um die Größe zu verringern von dieser alten Binärdatei dachten Sie, dass es sie nicht mehr gibt.Übrigens, dies gilt nicht nur für Binärdateien, sondern auch für alle offenen Dateien. Wenn Sie eine Datei in einem Prozess öffnen und die Datei entfernen, bleibt die Datei auf der Festplatte, bis dieser Prozess die Datei schließt (oder stirbt) Der Dateisystemtreiber (im Linux-Kernel) protokolliert, wie viele Verweise auf diesen Inode im Speicher vorhanden sind , und gibt den Inode erst von der Festplatte frei, wenn auch alle Verweise vom laufenden System freigegeben wurden.
Diese Frage basiert auf der falschen Annahme 2, dass das Nicht-Sperren der Seiten zu Fehlern führt. Das wird es nicht.
Es soll auf die gleiche Art und Weise funktionieren, aber es gibt einige "Fallstricke" mit NFS.
Manchmal können Sie die Artefakte beim Löschen einer Datei sehen, die noch in NFS geöffnet ist (wird in diesem Verzeichnis als versteckte Datei angezeigt).
Sie können NFS-Exporten auch Gerätenummern zuweisen, um sicherzustellen, dass diese beim Neustart des NFS-Servers nicht neu gemischt werden.
Die Grundidee ist jedoch dieselbe. Der NFS-Client-Treiber verwendet weiterhin Inodes und versucht, Dateien (auf dem Server) zu behalten, während auf den Inode verwiesen wird.
quelle
rename
Dies ist so ziemlich die einzige Datei- und Dateisystemoperation, die garantiert atomar ist (vorausgesetzt, wir überschreiten weder Dateisystem- noch Gerätegrenzen). Daher ist "temporäre Datei erstellen und dannrename
" das Standardmuster zum Aktualisieren von Dateien. Dies ist zum Beispiel auch das, was jeder Texteditor unter Unix verwendet.rename
ist Teil von POSIX. Zugegeben, es ist in Bezug auf ISO C enthalten (Abschnitt 7.21.4.2 im aktuellen Entwurf), aber es ist dort enthalten.Nein, das wird nicht passieren, weil der Kernel nicht zulässt, dass Sie in einer Datei, die gerade ausgeführt wird, irgendetwas zum Schreiben und Ersetzen öffnen. Eine solche Aktion schlägt fehl mit
ETXTBSY
[1]:Wenn dpkg usw. eine Binärdatei aktualisiert, wird sie nicht überschrieben, sondern verwendet
rename(2)
, um den Verzeichniseintrag einfach auf eine völlig andere Datei zu verweisen, und alle Prozesse, die noch Zuordnungen oder offene Handles zur alten Datei haben, verwenden sie weiterhin ohne Probleme .[1] Ein solcher Schutz gilt nicht für andere Dateien, die ebenfalls als "Text" (Live-Code / ausführbare Datei) betrachtet werden können: gemeinsam genutzte Bibliotheken, Java-Klassen usw .; Das Ändern einer solchen Datei, während sie von einem anderen Prozess zugeordnet wurde, führt zum Absturz. Unter Linux übergibt der Dynamic Linker die
MAP_DENYWRITE
Flagge pflichtbewusst anmmap(2)
, macht aber keinen Fehler - er hat keinerlei Auswirkungen.quelle
rename(2)
ist atomar; Sobald es abgeschlossen ist, verweist der Verzeichniseintrag auf die neue Datei. Die Prozesse, die zu diesem Zeitpunkt noch die alte Datei verwendeten, konnten nur über vorhandene Zuordnungen oder über offene Handles darauf zugreifen (die möglicherweise auf einen Waisen-Dentry verweisen, auf den nur noch über zugegriffen werden kann/proc/PID/fd
).Die Antwort von filbranden ist richtig, vorausgesetzt, der kontinuierliche Release-Prozess ersetzt die Dateien ordnungsgemäß über
rename
. Wenn dies nicht der Fall ist, die Datei jedoch direkt geändert wird, liegen die Dinge anders. Ihr mentales Modell ist jedoch immer noch falsch.Es besteht keine Möglichkeit, dass Dinge auf der Festplatte geändert werden und mit dem Seiten-Cache inkonsistent sind, da der Seiten-Cache die kanonische Version ist und die Version , die geändert wurde. Alle Schreibvorgänge in eine Datei erfolgen über den Seiten-Cache. Wenn es dort bereits vorhanden ist, werden die vorhandenen Seiten geändert. Wenn es noch nicht vorhanden ist, wird beim Versuch, eine Teilseite zu ändern, die gesamte Seite zwischengespeichert, gefolgt von einer Änderung, als wäre sie bereits zwischengespeichert. Schreibvorgänge, die sich über eine ganze Seite oder mehr erstrecken, können den Leseschritt, in dem sie eingelesen werden, mit ziemlicher Sicherheit optimieren. In jedem Fall gibt es nur eine kanonisch änderbare Version einer Datei (*), diejenige im Seiten-Cache .
(*) Ich habe leicht gelogen. Bei NFS und anderen Remote-Dateisystemen kann es mehr als ein Dateisystem geben, und diese implementieren in der Regel (je nachdem, welches und welche Mount- und serverseitigen Optionen verwendet werden) die Atomarität und Ordnungssemantik für Schreibvorgänge nicht korrekt. Aus diesem Grund betrachten viele von uns sie als grundlegend kaputt und lehnen es ab, sie in Situationen zu verwenden, in denen Schreibvorgänge gleichzeitig mit der Verwendung erfolgen.
quelle