2010-12-01 4 views
8

Ich möchte virtuellen Adressraum reserviert in meinem Prozess für Speicher, 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 Überbelegung zu verhindern (was durch eine detaillierte Abrechnung des gesamten festgeschriebenen Speichers geschieht).Müssen mmap/mprotect-readonly null Seiten in Richtung festgeschriebenem Speicher gezählt werden?

Wenn ich nur die Daten, die meine Anwendung nicht mehr von der Belegung des physischen Speichers oder die Auslagerung auf die Festplatte (Ressourcenverschwendung so oder so) verhindern will, kann ich den Kernel, der es nicht benötigt, oder mmap neue Nullseiten über Spitze davon. Aber keiner dieser Ansätze wird notwendigerweise die Menge an Speicher reduzieren, die als festgeschrieben gilt, und die anderen Prozesse können dann nicht verwendet werden.

Was passiert, wenn ich die Seiten durch neue Nullseiten ersetze, die schreibgeschützt sind? Meine Absicht ist, dass sie nicht auf festgeschriebenen Speicher zählen, und weiter, dass ich später mprotect verwenden kann, um sie beschreibbar zu machen, und dass es fehlschlagen würde, wenn sie beschreibbar über das festgeschriebene Speicherlimit gehen würde. Ist mein Verständnis richtig? Ob das funktioniert?

+1

Ein Nur-Lese-Seite sollte nicht in einem Verfahren in Betracht gezogen werden begehen Ladung (Ich habe keinen Bezug zur Hand haben, so ist dies keine Antwort) und Linux bietet die MAP_NORESERVE Flag, das Sie ein noch geben sollte stärker Garantie. Aber ich muss fragen: Warum hast du das Bedürfnis, Speicher zu reservieren, der nicht benutzt wird? – Anon

+0

Bad Things (tm) würde passieren, wenn die gleichen virtuellen Adressen durch "mmap" (zufällig) zugeordnet wurden, ohne dass das Programm davon Kenntnis hatte. :-) Wie bei MAP_NORESERVE befürchte ich, dass die Seiten nicht gezählt werden, auch wenn ich sie später beschreibbar mache. Ich nehme an, ich könnte sie einfach mit neuen Nullseiten überlesen. –

+0

Welche schlimmen Dinge würden passieren? Warum muss Ihr Programm den zuvor verwendeten Adressraum niemals wiederverwenden? Das scheint sehr ungewöhnlich. – Angus

Antwort

1

Wenn Sie die Seite nicht verwenden (lesen oder schreiben), wird sie nicht in Ihren Adressraum übertragen (nur reserviert).

Aber Ihr Adressraum ist begrenzt, so dass Sie nicht so spielen können, wie Sie wollen/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. Werfen Sie einen Blick auf diese Thema: „mprotect() schlug fehl: Speicher kann nicht zugewiesen“: http://thread.gmane.org/gmane.comp.lib.glibc.user/538/focus=976052

+3

Es wird * auf virtuelle Größe geladen, aber nicht auf RSS. –

1

Unter Linux hat overcommit Annahme nicht deaktiviert wurde, können Sie die MAP_NORESERVE Flagge zu mmap verwenden können, die dass die Seite sicherstellen in Frage wird vor dem Zugriff nicht als zugeordneter Speicher abgerechnet. Wenn die Überkompensierung vollständig deaktiviert wurde, finden Sie weitere Informationen zu Seiten mit mehreren Zuordnungen.

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 vermeiden, auf die Seite überhaupt zuzugreifen, indem Sie mprotect in PROT_NONE.

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, trennen Sie die Verbindung, ftruncate, auf eine vernünftige Anzahl von Seiten, dann mmap wiederholt bei Offset 0 in die Datei. Dies garantiert absolut, dass der Speicher nur einmal gegen den Speicherverbrauch Ihres Programms zählt. Sie können sogar MAP_PRIVATE verwenden, um es automatisch neu zuzuweisen, wenn Sie auf die Seite schreiben.

Dies kann eine höhere Speicherauslastung haben als die MAP_NORESERVE Technik (sowohl für Kernel-Tracking-Daten und für die Seiten der Temp-Datei selbst), so würde ich jedoch MAP_NORESERVE stattdessen empfehlen, wenn verfügbar. Wenn Sie diese Technik verwenden, versuchen Sie, die Region, die gemappt wird, ziemlich groß zu machen (und setzen Sie sie unter Linux auf /dev/shm, um die tatsächliche Datenträger-IO zu vermeiden). Jeder einzelne Aufruf von mmap wird eine gewisse Menge an (nicht-austauschbarem) Kernel-Speicher verbrauchen, um es zu verfolgen, also ist es gut, diesen Countdown zu halten.

+1

Nützliche Informationen insgesamt, aber 'MAP_NORESERVE' ist nicht nützlich. Es wird ignoriert, wenn die Überbelegung vollständig deaktiviert ist. –

+0

Glauben Sie, dass das Mapping '/ dev/zero' genauso funktionieren würde wie eine temporäre Datei in Ihrem Vorschlag? –

+0

@ Zan, nein. '/ dev/zero'-Maps sind die gleichen wie normale' MAP_ANON'-Maps und werden daher ebenso wie jede andere Speicherzuweisung berücksichtigt. – bdonlan