Ich möchte in meinem Prozess reservierten virtuellen Adressraum für Speicher reservieren, der zuvor verwendet wurde, aber derzeit nicht benötigt wird. Ich interessiere mich für die Situation, in der der Host-Kernel Linux ist und konfiguriert ist, um eine Überkompensierung zu verhindern (was durch eine detaillierte Verbuchung des gesamten festgeschriebenen Speichers geschieht).
Wenn ich nur verhindern möchte, dass die Daten, die meine Anwendung nicht mehr benutzt, den physischen Speicher belegen oder auf die Festplatte ausgelagert werden (Ressourcenverschwendung), kann ich madvise
dem Kernel, der nicht benötigt wird, oder mmap
new geben Null Seiten darüber. Aber keiner dieser Ansätze wird notwendigerweise die Menge an Speicher reduzieren, die als "committed" gilt, was dann an anderen Prozessen verhindert wird.
Was passiert, wenn ich die Seiten durch neue Nullseiten ersetze, die schreibgeschützt sind? Meine Absicht ist, dass sie nicht auf festgeschriebenen Speicher angerechnet werden und dass ich später mprotect
verwenden kann, um sie beschreibbar zu machen, und dass es scheitern würde, wenn sie schreibbar gemacht werden würde, würde das festgelegte Speicherlimit überschreiten. Ist mein Verständnis richtig? Wird das funktionieren?
Wenn Sie die Seite nicht verwenden (lesen oder schreiben), wird sie nicht an Ihren Adressraum übertragen (nur reserviert).
Aber Ihr Adressraum ist begrenzt, so dass Sie nicht so spielen können, wie Sie möchten / mögen.
Siehe zum Beispiel ElectricFence, die für eine große Anzahl von Zuweisungen fehlschlagen kann, weil "nul page / guard page" (anonymer Speicher ohne Zugriff) eingefügt wird. Sehen Sie sich diesen Thread an: "mprotect () ist fehlgeschlagen: Speicher kann nicht zugewiesen werden": Ссылка
Unter Linux wurde unter der Annahme, dass die Überbelegung nicht deaktiviert wurde, das Flag MAP_NORESERVE
für mmap
verwendet. Dadurch wird sichergestellt, dass die betreffende Seite vor dem Zugriff nicht als zugewiesener Speicher behandelt wird. Wenn die Überbelegung vollständig deaktiviert wurde, finden Sie weitere Informationen zu Seiten mit mehreren Abbildungen.
Beachten Sie, dass sich das Verhalten von Linux für null Seiten in der Vergangenheit manchmal geändert hat; Bei einigen Kernel-Versionen würde das einfache Lesen der Seite dazu führen, dass sie zugewiesen wird. Bei anderen ist ein Schreiben notwendig. Beachten Sie, dass die Schutzflags keine direkte Zuweisung verursachen. Sie können jedoch verhindern, dass Sie versehentlich eine Zuweisung auslösen. Daher sollten Sie für die meisten zuverlässigen Ergebnisse den Zugriff auf die Seite überhaupt nicht mit mprotect
ing mit PROT_NONE
vermeiden.
Als weitere, portablere Option können Sie die gleiche Seite an mehreren Standorten zuordnen. Das heißt, erstellen und öffnen Sie eine leere temporäre Datei, heben Sie die Verknüpfung auf, ftruncate
auf eine vernünftige Anzahl von Seiten, und mmap
wiederholt bei Offset 0 in die Datei. Dies garantiert absolut, dass der Speicher nur einmal gegen die Speicherbelegung Ihres Programms zählt. Sie können sogar MAP_PRIVATE
verwenden, um sie automatisch neu zuzuweisen, wenn Sie auf die Seite schreiben.
Dies kann jedoch eine höhere Speicherbelegung haben als die MAP_NORESERVE
-Technik (sowohl für Kernel-Tracking-Daten als auch für die Seiten der temporären Datei selbst). Daher würde ich empfehlen, stattdessen MAP_NORESERVE
zu verwenden. Wenn Sie diese Technik verwenden, versuchen Sie, die Region, die gemappt wird, ziemlich groß zu machen (und setzen Sie sie in /dev/shm
, wenn Sie unter Linux sind, um die tatsächliche Datenträger-IO zu vermeiden). Jeder einzelne mmap
-Aufruf benötigt eine gewisse Menge (nicht austauschbaren) Kernel-Speicher, um es zu verfolgen, also ist es gut, diesen Countdown zu halten.
Tags und Links c linux mmap overcommit