mlock(2) Speicher ver- und entriegeln

Other Alias

mlock2, munlock, mlockall, munlockall

ÜBERSICHT

#include <sys/mman.h>


int mlock(const void *addr, size_t len);
int mlock2(const void *addr, size_t len, int flags);
int munlock(const void *addr, size_t len);

int mlockall(int flags);
int munlockall(void);

BESCHREIBUNG

mlock(), mlock2() und mlockall() verriegeln den gesamten oder einen Teil des virtuellen Adressraums des aufrufenden Prozesses im RAM und verhindern, dass der Speicherinhalt in den Swap-Bereich ausgelagert wird.

munlock() und munlockall () führen die umgekehrte Operation durch bzw. entriegeln den gesamten oder einen Teil des virtuellen Adressraums des aufrufenden Prozesses, sodass die Seiten im angegebenen virtuellen Adressbereich wieder ausgelagert werden können, wenn das von der Kernel-Speicherverwaltung verlangt wird.

Ver- und Entriegelung des Speichers werden für ganze Speicherseiten durchgeführt.

mlock(), mlock2() und munlock()

mlock() verriegelt Seiten im Adressbereich, der bei addr beginnt und sich über len Byte erstreckt. Alle Seiten, die einen Teil des angegebenen Adressbereichs enthalten, verbleiben nach einem erfolgreichen Aufruf garantiert im RAM; die Seiten bleiben garantiert im RAM, bis sie wieder entriegelt werden.

mlock2() verriegelt auch Seiten im Adressbereich, der bei addr beginnt und sich über len Byte erstreckt. Der Status der Seiten, die einen Teil des angegebenen Adressbereichs enthalten, nach einem erfolgreichen Aufruf hängt vom Wert des flags-Arguments ab.

Das Argument flags kann entweder 0 oder eine der folgenden Konstanten sein:

MLOCK_ONFAULT
Lock pages that are currently resident and mark the entire range to have pages locked when they are populated by the page fault.

Wenn flags 0 ist, verhält sich mlock2() genau so wie mlock().

Hinweis: Derzeit gibt es keinen Glibc-Wrapper für mlock2(), daher muss es über syscall(2) aufgerufen werden.

munlock() entriegelt Seiten im Adressbereich, der mit addr beginnt und sich über len Byte erstreckt. Nach diesem Aufruf können alle Seiten, die einen Teil des angegebenen Speicherbereichs umfassen, erneut vom Kernel in externen Swap-Speicher ausgelagert werden.

mlockall() und munlockall()

mlockall() sperrt das Paging für alle Seiten, die in den Adressraum des aufrufenden Prozesses eingebunden sind. Dieses bezieht sich auf die Seiten von Code-, Daten- und Stacksegment genauso wie auf gemeinsame Bibliotheken, Kernel-Daten im Userspace, Shared Memory und auf den Speicher abgebildete Dateien. Es wird garantiert, dass alle eingebundenen Speicherseiten im RAM bleiben, wenn der Aufruf von mlockall() erfolgreich beendet wird. Es wird darüber hinaus garantiert, dass die Seiten solange im RAM bleiben, bis sie wieder entriegelt werden.

Das Argument flags wird mittels logischem ODER aus einer oder mehreren der folgenden Konstanten konstruiert:

MCL_CURRENT
sperrt alle Seiten, die momentan in den Adressraum des Prozesses eingeblendet sind.
MCL_FUTURE
sperrt alle Seiten, die in Zukunft in den Adressraum des Prozesses eingeblendet werden. Das könnten zum Beispiel neue Adress-Seiten sein, die bei einem sich vergrößernden Heap und Stack benötigt werden, Dateien, die in den Speicher eingeblendet werden, oder gemeinsam benutzte Speicherbereiche.
MCL_ONFAULT (seit Linux 4.4)
Used together with MCL_CURRENT, MCL_FUTURE, or both. Mark all current (with MCL_CURRENT) or future (with MCL_FUTURE) mappings to lock pages when they are faulted in. When used with MCL_CURRENT, all present pages are locked, but mlockall() will not fault in non-present pages. When used with MCL_FUTURE, all future mappings will be marked to lock pages when they are faulted in, but they will not be populated by the lock when the mapping is created. MCL_ONFAULT must be used with either MCL_CURRENT or MCL_FUTURE or both.

Falls MCL_FUTURE angegeben wurde, kann ein späterer Systemaufruf (z. B. mmap(2), sbrk(2), malloc (3)) fehlschlagen, wenn durch ihn die Zahl gesperrter Bytes das zulässige Maximum überschreiten würde (siehe unten). Unter den gleichen Voraussetzungen kann eine Vergrößerung des Stacks ebenfalls fehlschlagen: der Kernel wird den Stack-Ausbau verweigern und dem Prozess ein SIGSEGV-Signal schicken.

munlockall() entriegelt alle in den Addressraum des aufrufenden Prozesses eingeblendeten Seiten.

RÜCKGABEWERT

Bei Erfolg geben diese Systemaufrufe 0 zurück. Bei einem Fehler wird -1 zurückgegeben, errno entsprechend gesetzt und keine Änderungen an den Sperren im Adressraum des Prozesses durchgeführt.

FEHLER

ENOMEM
(Linux 2.6.9 und später) Der Aufrufende hatte eine weiche Ressourcenbegrenzung RLIMIT_MEMLOCK ungleich null, versuchte aber über diese Grenze hinaus Speicher zu verriegeln. Diese Grenze wird nicht erzwungen, wenn der Prozess privilegiert ist (CAP_IPC_LOCK).
ENOMEM
(Linux 2.4 und früher) Der aufrufende Prozess versuchte mehr als die Hälfte des RAMs zu verriegeln.
EPERM
Der Aufrufende ist nicht privilegiert, benötigt aber zur Durchführung der angeforderten Operation Privilegien (CAP_IPC_LOCK).

Für mlock(), mlock2() und munlock():

EAGAIN
Ein Teil des angegebenen Adressbereichs oder der gesamte Adressbereich konnten nicht verriegelt werden.
EINVAL
Das Ergebnis der Addition addr+len war kleiner als addr (z. B. kann die Addition einen Überlauf verursacht haben.)
EINVAL
(Nicht unter Linux) addr war kein Vielfaches der Seitengröße.
ENOMEM
Ein Teil des angegebenen Adressbereichs entspricht nicht Seiten, die in den Adressraum des Prozesses eingeblendet sind.
ENOMEM
Locking or unlocking a region would result in the total number of mappings with distinct attributes (e.g., locked versus unlocked) exceeding the allowed maximum. (For example, unlocking a range in the middle of a currently locked mapping would result in three mappings: two locked mappings at each end and an unlocked mapping in the middle.)

Für mlock2():

EINVAL
Es wurden unbekannte Flags angegeben.

Für mlockall():

EINVAL
Es wurden entweder unbekannte flags angegeben, oder MCL_ONFAULT wurde weder mit MCL_FUTURE noch mit MCL_CURRENT angegeben.

Für munlockall():

EPERM
(Linux 2.6.8 und früher) Der Aufrufende war nicht privilegiert (CAP_IPC_LOCK).

VERSIONEN

mlock2(2) ist seit Linux 4.4 verfügbar.

KONFORM ZU

POSIX.1-2001, POSIX.1-2008, SVr4.

mlock2 () ist Linux-spezifisch.

VERFÜGBARKEIT

Auf POSIX-Systemen, auf denen mlock() und munlock() verfügbar sind, ist _POSIX_MEMLOCK_RANGE in <unistd.h> definiert und die Anzahl der Bytes pro Seite kann der Konstante PAGESIZE (wenn sie definiert ist) in <limits.h> entnommen werden oder durch einen Aufruf von sysconf(_SC_PAGESIZE) bestimmt werden.

Auf POSIX-Systemen, auf denen mlockall() und munlockall() verfügbar sind, ist _POSIX_MEMLOCK in <unistd.h> als ein Wert größer als 0 definiert. (Siehe auch sysconf(3).)

ANMERKUNGEN

Das Sperren von Speicher hat zwei Hauptanwendungen: Echtzeitalgorithmen und Hochsicherheits-Datenverarbeitung. Echtzeitanwendungen erfordern deterministisches Timing, und, wie auch Scheduling, ist Paging einer der Hauptgründe für unerwartete Verzögerungen in der Programmausführung. Echtzeitanwendungen werden außerdem für gewöhnlich mit sched_setscheduler(2) auf einen Echtzeit-Scheduler umschalten. Kryptographische Sicherheitssoftware stellt oft sicherheitskritische Bytes wie Passwörter oder geheime Schlüssel als Datenstrukturen dar. Durch Paging könnten diese geheimen Daten auf ein permanentes Swap-Speichermedium übertragen werden, von wo aus sie auch dann noch Dritten zugänglich sein können, lange nachdem das Programm die geheimen Daten aus dem RAM gelöscht und sich beendet hat. (Bedenken Sie bitte, dass der Suspend-Modus von Laptops und manchen Desktop-Rechnern, unabhängig von Speichersperren, eine Kopie des RAMs auf der Platte speichern wird.)

Echtzeitprozesse, die mittels mlockall() Verzögerungen durch Page Faults (Seitenfehler) vermeiden, sollten ausreichend gesperrte Stackseiten reservieren, bevor sie in die zeitkritische Phase treten, sodass durch einen Funktionsaufruf kein Fehler entstehen kann. Dies kann durch den Aufruf einer Funktion erreicht werden, die eine ausreichend große automatische Variable (ein Feld) erzeugt und in den Speicher schreibt, in dem die Variable liegt, um diese Stackseiten zu belegen. Auf diesem Wege werden genug Seiten für den Stack bereitgestellt und können im RAM verriegelt werden. Der Schreibvorgang stellt sicher, dass nicht einmal ein Schreib-Kopier-Seitenfehler in der kritischen Phase eintreten kann.

Speicherverriegelungen werden nicht an mittels fork(2) erzeugte Kindprozesse vererbt und durch einen Aufruf von execve(2) oder das Ende des Prozesses automatisch entfernt (entriegelt). Die Einstellungen MCL_FUTURE und MCL_FUTURE | MCL_ONFAULT in mlockall() werden nicht von einem Kindprozess ererbt, der mittels fork(2) erzeugt wurde und werden während eines execve(2) gelöscht.

Die Speicherverriegelung wird automatisch entfernt, wenn der Adressbereich mittels munmap(2) ausgeblendet wird.

Speichersperren werden nicht hochgezählt (»gestapelt«), das heißt, Seiten die mehrmals durch den Aufruf von mlockall(), mlock2() oder mlock() gesperrt wurden werden durch einen einzigen Aufruf von munlock() für den entsprechenden Bereich oder durch munlockall() sofort wieder freigegeben. Seiten, die an verschiedene Orte oder für verschiedene Prozesse eingeblendet wurden, bleiben solange im RAM verriegelt, wie sie mindestens an einem Ort oder durch einen Prozess benötigt werden.

Wenn einem Aufruf von mlockall(), der das MCL_FUTURE-Flag nutzt, ein weiterer Aufruf folgt, der dieses Flag nicht angibt, gehen die durch den Aufruf von MCL_FUTURE erwirkten Änderungen verloren.

The mlock2() MLOCK_ONFAULT flag and the mlockall() MCL_ONFAULT flag allow efficient memory locking for applications that deal with large mappings where only a (small) portion of pages in the mapping are touched. In such cases, locking all of the pages in a mapping would incur a significant penalty for memory locking.

Linux-Anmerkungen

Unter Linux runden mlock(), mlock2() und munlock() addr automatisch zur nächsten Seitengrenze ab. Da aber die POSIX.1-Spezifikation von mlock() und munlock() Implementierungen gestattet, welche die Ausrichtung von addr an Seitengrenzen fordern, sollten portable Anwendungen die Ausrichtung sicherstellen.

Das Feld VmLck der Linux-spezifischen Datei /proc/PID/status gibt an, wie viele Kilobytes Speicher der Prozess mit der ID PID mittels mlock(), mlock2(), mlockall() und mmap(2) mit dem Flag MAP_LOCKED verriegelt hat.

Grenzen und Zugriffsrechte

Bis einschließlich Linux 2.6.8 muss ein Prozess privilegiert sein (CAP_IPC_LOCK), um Speicher zu verriegeln. Die weiche Systembegrenzung RLIMIT_MEMLOCK bestimmt einen Speicher-Schwellwert, den der Prozess verriegeln darf.

Seit Linux 2.6.9 kann ein privilegierter Prozess unbegrenzt Speicher verriegeln. Die weiche Systembegrenzung RLIMIT_MEMLOCK legt stattdessen fest, wieviel Speicher ein nicht privilegierter Prozess verriegeln darf.

FEHLER

In den Linux-Kerneln 2.4.x bis einschließlich 2.4.17 bewirkte ein Fehler, dass das Flag MCL_FUTURE von mlockall() über einen Aufruf von fork(2) vererbt wurde. Dies wurde in Kernel 2.4.18 behoben.

Seit Kernel 2.6.9 werden, falls ein privilegierter Prozess mlockall(MCL_FUTURE) aufruft und anschließend Privilegien aufgibt (die Capability CAP_IPC_LOCK verliert, weil er beispielsweise seine effektive UID auf einen von null verschiedenen Wert setzt), nachfolgende Speicherzuordnungen (z.B. mmap(2), brk(2)) fehlschlagen, wenn die Ressourcengrenze RLIMIT_MEMLOCK berührt wird.

KOLOPHON

Diese Seite ist Teil der Veröffentlichung 4.06 des Projekts Linux-man-pages. Eine Beschreibung des Projekts, Informationen, wie Fehler gemeldet werden können sowie die aktuelle Version dieser Seite finden sich unter https://www.kernel.org/doc/man-pages/.

ÜBERSETZUNG

Die deutsche Übersetzung dieser Handbuchseite wurde von Michaela Hohenner <[email protected]>, Hanno Wagner <[email protected]>, Martin Schulze <[email protected]>, Martin Eberhard Schauer <[email protected]> und Mario Blättermann <[email protected]> erstellt.

Diese Übersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 oder neuer bezüglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG übernommen.

Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an <[email protected]>.