Provided by: manpages-de-dev_4.27.0-1_all 

BEZEICHNUNG
mmap, munmap - (un)mapt Dateien oder Geräte im Speicher
BIBLIOTHEK
Standard-C-Bibliothek (libc, -lc)
ÜBERSICHT
#include <sys/mman.h>
void *mmap(void Adr[.laenge], size_t laenge, int prot, int Schalter,
int dd, off_t Versatz);
int munmap(void Adr[.laenge], size_t laenge);
Siehe ANMERKUNGEN für Informationen über Feature-Test-Makros-Anforderungen.
BESCHREIBUNG
mmap() erstellt ein neues Mapping in den virtuellen Adressraum des aufrufenden Prozesses. Die
Anfangsadresse für dieses neue Mapping wird in Adr angegeben. Das Argument laenge gibt an, welche Größe
das Mapping haben soll (dies muss größer als 0 sein).
Falls Adr NULL ist, wählt der Kernel die (Seiten-ausgerichtete) Adresse aus, an der das Mapping erstellt
wird. Dies ist die portabelste Methode, ein neues Mapping zu erstellen. Falls Adr nicht NULL ist, wertet
der Kernel die Adresse als Hinweis, wo das Mapping erstellt werden soll. Unter Linux wird das Mapping
dann eine Speicherseitengrenze in der Nähe auswählen (allerdings immer identisch zu oder oberhalb von dem
durch /proc/sys/vm/mmap_min_addr festgelegten Wert) und versuchen, dort ein Mapping zu erstellen. Falls
dort bereits ein anderes Mapping existiert, dann wählt der Kernel eine neue Adresse, die den Hinweis
berücksichtigen kann, aber nicht muss. Die Adresse des neuen Mappings wird als Ergebnis des Aufrufs
zurückgegeben.
Die Inhalte eines Datei-Mappings werden initialisiert, indem laenge Byte aus der Datei (oder einem
anderen Objekt), die durch den Dateideskriptor dd beschrieben wird, ab dem Versatz Versatz verwendet
werden. Dies ist anders als beim anonymen Mapping, siehe MAP_ANONYMOUS unten. Versatz muss ein Vielfaches
der Seitengröße sein, die von sysconf(_SC_PAGE_SIZE) zurückgegeben wird.
Nachdem der mmap()-Aufruf zurückgekehrt ist, kann der Dateideskriptor dd sofort geschlossen werden, ohne
dass das Mapping ungültig wird.
Das Argument prot beschreibt den gewünschten Speicherschutz des Mappings (und darf nicht im Widerspruch
zum Öffnungsmodus der Datei stehen). Es ist entweder PROT_NONE oder das bitweise ODER von einem oder
mehreren der folgenden Schalter:
PROT_EXEC Seiten können ausgeführt werden.
PROT_READ Seiten dürfen gelesen werden.
PROT_WRITE Seiten dürfen beschrieben werden.
PROT_NONE Auf die Seiten darf nicht zugegriffen werden.
Das Argument »Schalter«
Das Argument Schalter bestimmt, ob Aktualisierungen des Mappings für andere Prozesse sichtbar sind, die
denselben Bereich mappen und ob Aktualisierungen auch in die zugrundeliegende Datei weitergereicht
werden. Dieses Verhalten wird durch genau einen der folgenden Werte in Schalter festgelegt:
MAP_SHARED
Das Mapping gemeinsam benutzen. Aktualisierungen dieses Mappings sind für andere Prozesse in dem
gleichen Bereich sichtbar und (falls es sich um Datei-basierende Mappings handelt) werden zu der
zugrundeliegenden Datei weitergereicht. (Um genau zu steuern, wann Aktualisierungen zu der
zugrundeliegenden Datei weitergereicht werden, muss msync(2) eingesetzt werden.)
MAP_SHARED_VALIDATE (seit Linux 4.15)
Dieser Schalter stellt das gleiche Verhalten wie MAP_SHARED bereit, außer dass MAP_SHARED-Mappings
unbekannte Schalter in Schalter ignorieren. Im Gegensatz überprüft der Kernel, wenn er Mappings
mittels MAP_SHARED_VALIDATE erstellt, dass alle übergebenen Schalter bekannt sind und schlägt mit
dem Fehler EOPNOTSUPP bei unbekannten Schaltern fehl. Dieser Mapping-Typ wird auch benötigt, um
bestimmte Mapping-Schalter (z.B. MAP_SYNC) verwenden zu können.
MAP_PRIVATE
Erstellt ein privates, beim Kopieren zu schreibendes Mapping. Aktualisierungen an dem Mapping sind
für andere Prozesse, die die gleiche Datei mappen, nicht sichtbar, und werden nicht an die
zugrundeliegende Datei weitergeleitet. Es ist nicht spezifiziert, ob Änderungen an der Datei, die
nach dem Aufruf von mmap() erfolgen, in der gemappten Region sichtbar sind.
Sowohl MAP_SHARED als auch MAP_PRIVATE werden in POSIX.1-2001 und POSIX.1-2008 beschrieben.
MAP_SHARED_VALIDATE ist eine Linux-Erweiterung.
Zusätzlich können null oder mehrere der folgenden Werte mit OR in Schalter hinzugefügt werden:
MAP_32BIT (seit Linux 2.4.20, 2.6)
Legt das Mapping in die ersten zwei Gigabyte des Prozessadressraums. Dieser Schalter wird nur auf
X86-64 für 64-Bit-Programme unterstützt. Er wurde hinzugefügt, damit Thread-Stacks irgendwo
innerhalb der ersten 2 GB Speicher zugewiesen werden können, damit die Leistung des
Kontext-Umschaltens auf einigen der ersten 64-Bit-Prozessoren erhöht wird. Moderne
X86-64-Prozessoren haben dieses Leistungsproblem nicht mehr, wodurch der Einsatz dieses Schalters
auf diesen Systemen nicht mehr benötigt wird. Der Schalter MAP_32BIT wird ignoriert, wenn
MAP_FIXED gesetzt ist.
MAP_ANON
Synonym für MAP_ANONYMOUS; zur Kompatibilität mit anderen Implementierungen bereitgestellt.
MAP_ANONYMOUS
Diesem Mapping liegt keine Datei zugrunde; ihr Inhalt wird mit Nullen initialisiert. Das Argument
dd wird ignoriert, einige Implementierungen verlangen aber, dass dd -1 ist, falls MAP_ANONYMOUS
(oder MAP_ANON) festgelegt ist, und portable Anwendungen sollten dies sicherstellen. Das Argument
Versatz sollte 0 sein. Die Unterstützung für MAP_ANONYMOUS mit MAP_SHARED wurde in Linux 2.4
hinzugefügt.
MAP_DENYWRITE
Dieser Schalter wird ignoriert. (Vor langer Zeit – Linux 2.0 und älter – signalisierte er, dass
Schreibversuche auf die zugrundeliegende Datei mit ETXTBSY fehlschlagen sollten. Dies war aber
eine Quelle von Diensteverweigerungsangriffen.
MAP_EXECUTABLE
Dieser Schalter wird ignoriert.
MAP_FILE
Kompatibilitätsschalter. Ignoriert.
MAP_FIXED
Adr wird nicht als Hinweis interpretiert; legt das Mapping genau an dieser Adresse an. Adr muss
geeignet ausgerichtet sein: bei den meisten Architekturen reicht ein Vielfaches der Seitengröße
aus, allerdings könnten einige Architekturen zusätzliche Anforderungen stellen. Falls der mit Adr
und laenge festgelegte Speicherbereich bestehende Mappings überlappt, dann wird der überlappende
Anteil des bestehenden Mappings verworfen. Falls die angegebene Adresse nicht verwandt werden
kann, wird mmap() fehlschlagen.
Software, die Portierbarkeit anstrebt, sollte den Schalter MAP_FIXED mit Vorsicht verwenden und
dabei berücksichtigen, dass sich die genaue Anordnung der Mappings des Prozesses im Speicher
deutlich zwischen Linuxversionen, C-Bibliotheksversionen und Betriebssystemveröffentlichungen
unterscheiden kann. Lesen Sie die Erörterung dieses Schalters im Abschnitt ANMERKUNGEN sorgfältig!
MAP_FIXED_NOREPLACE (seit Linux 4.17)
Dieser Schalter stellt ein Verhalten bereit, das MAP_FIXED im Hinblick auf die Erzwingung von Adr
ähnelt, sich aber dadurch unterscheidet, dass MAP_FIXED_NOREPLACE einen bereits bestehenden,
gemappten Bereich durcheinanderbringt. Falls der angeforderte Bereich mit einem bestehenden
Mapping kollidieren würde, dann schlägt dieser Aufruf mit EEXIST fehl. Dieser Schalter kann daher
für atomare (im Hinblick auf andere Threads) Versuche, einen Adressbereich zu mappen, verwandt
werden: ein Thread hat Erfolg, alle anderen berichten einen Fehlschlag.
Beachten Sie, dass ältere Kernel, die den Schalter MAP_FIXED_NOREPLACE nicht erkennen,
typischerweise (bei der Erkennung einer Kollision mit einem bereits bestehenden Mapping) auf den
Verhaltenstyp von »nicht-MAP_FIXED« zurückfallen: sie liefern eine Adresse zurück, die sich von
der angeforderten Adresse unterscheidet. Daher sollte rückwärtskompatible Software die
zurückgelieferte Adresse mit der angeforderten Adresse vergleichen.
MAP_GROWSDOWN
Dieser Schalter wird für Stacks verwandt. Er zeigt dem Kernelsystem für virtuellen Speicher an,
dass sich das Mapping nach unten im Speicher ausdehnen soll. Die zurückgelieferte Adresse ist eine
Seite tiefer als der Speicherbereich, der tatsächlich im virtuellen Adressraum des Prozesses
erstellt wird. Wird eine Adresse in der »Wächter«-Seite unterhalb des Mappings berührt, dann
wächst das Mapping um eine Seite. Dieses Wachstum kann wiederholt werden, bis das Mapping bis auf
eine Seite innerhalb des hohen Endes des nächst-niedrigeren Mappings anwächst - zu diesem
Zeitpunkt führt das Berühren der »Wächter«-Seite zu einem SIGSEGV-Signal.
MAP_HUGETLB (seit Linux 2.6.32)
Reserviert das Mapping mittels »großer« Speicherseiten. Siehe die Linux-Kernelquelldatei
Documentation/admin-guide/mm/hugetlbpage.rst sowie die nachfolgenden ANMERKUNGEN für weitere
Details.
MAP_HUGE_2MB
MAP_HUGE_1GB (seit Linux 3.8)
Wird in Zusammenhang mit MAP_HUGETLB verwandt, um alternative hugetlb-Seitengrößen (respektive
2 MB und 1 GB) auf Systemen auszuwählen, die mehrere hugetlb-Seitengrößen unterstützen.
Allgemeiner kann die gewünschte Größe der großen Speicherseiten durch Kodierung des Logarithmus
zur Basis 2 der gewünschten Seitengröße in den sechs Bits am Versatz MAP_HUGE_SHIFT konfiguriert
werden. (Ein Wert 0 in diesem Bitfeld stellt die standardmäßige große Speicherseitengröße bereit;
die Vorgabegröße großer Speicherseiten kann mittels des durch /proc/meminfo offengelegten Feldes
Hugepagesize ermittelt werden.) Daher sind die obigen zwei Konstanten wie folgt definiert:
#define MAP_HUGE_2MB (21 << MAP_HUGE_SHIFT)
#define MAP_HUGE_1GB (30 << MAP_HUGE_SHIFT)
Der von dem System unterstützte Bereich der Größe der großen Speicherseiten kann durch Auflisten
der Unterverzeichnisse in /sys/kernel/mm/hugepages ermittelt werden.
MAP_LOCKED (seit Linux 2.5.37)
Markiert den gemappten Bereich auf die gleiche Art wie mlock(2). Diese Implementierung wird
versuchen, den gesamten Bereich vorzubelegen (»prefault«) aber der Aufruf von mmap() wird nicht
mit ENOMEM fehlschlagen, falls dies nicht gelingt. Daher können später große Ausnahmebehandlungen
passieren. Daher ist die Semantik nicht so stark wie mlock(2). Sie sollten mmap() mit mlock(2)
verwenden, wenn große Ausnahmebehandlungen nach der Initialisierung des Mappings nicht
akzeptierbar sind. Der Schalter MAP_LOCKED wird unter älteren Kerneln ignoriert.
MAP_NONBLOCK (seit Linux 2.5.46)
Dieser Schalter ergibt nur im Zusammenhang mit MAP_POPULATE Sinn. Es wird kein Vorauslesen
durchgeführt, es werden Seitentabelleneinträge nur für Seiten erstellt, die bereits im RAM
vorhanden sind. Seit Linux 2.6.23 führt dieser Schalter dazu, dass MAP_POPULATE nichts macht.
Irgendwann könnte die Kombination von MAP_POPULATE und MAP_NONBLOCK wieder implementiert werden.
MAP_NORESERVE
Reserviert für dieses Mapping keinen Auslagerungsspeicher. Wenn Auslagerungsspeicher reserviert
wird, muss garantiert werden, dass Änderungen an dem Mapping möglich sind. Wird kein
Auslagerungsspeicher reserviert, könnte beim Schreiben ein SIGSEGV empfangen werden, falls kein
physischer Speicher verfügbar ist. Siehe auch die Diskussion der Datei
/proc/sys/vm/overcommit_memory in proc(5). Vor Linux 2.6 hatte dieser Schalter nur für private,
schreibbare Mappings eine Wirkung.
MAP_POPULATE (seit Linux 2.5.46)
Belegt (»prefault«) Seitentabellen für ein Mapping. Für ein Datei-Mapping führt dies zu einem
Vorablesen der Datei. Dies hilft dabei, später Blockierungen bei Seitenausnahmebehandlungen zu
vermeiden. Der Aufruf mmap() schlägt nicht fehl, falls das Mapping nicht belegt werden kann
(beispielsweise aufgrund von Beschränkungen der Anzahl der gemappten großen Seiten bei der
Verwendung von MAP_HUGETLB). Die Unterstützung für MAP_POPULATE zusammen mit privaten Mappings
wurde in Linux 2.6.23 hinzugefügt.
MAP_STACK (seit Linux 2.6.27)
Reserverviert ein Mapping an einer Adresse, die für einen Stack eines Prozesses oder Threads
geeignet ist.
Dieser Schalter löst derzeit nichts aus. Durch Einsatz dieses Schalters können Anwendungen aber
transparent sicherstellen, dass sie die Unterstützung erlangen, wenn dieser Schalter in der
Zukunft implementiert wird. Daher wird er in der Glibc-Threading-Implementierung verwandt, um der
Tatsache Rechnung zu tragen, dass auf einigen Architekturen (später) eine besondere Behandlung von
Stack-Zuweisungen nötig sein könnte. Ein weiterer Grund, diesen Schalter einzusetzen, ist die
Portabilität: MAP_STACK existiert (und hat eine Auswirkung) auf einigen anderen Systemen (z.B.
einigen BSDs).
MAP_SYNC (seit Linux 4.15)
Dieser Schalter ist nur mit dem Mapping-Typ MAP_SHARED_VALIDATE verfügbar. Mappings vom Typ
MAP_SHARED ignorieren diesen Schalter ohne Rückmeldung. Dieser Schalter wird nur für Dateien, die
DAX (direktes Mapping von dauerhaftem Speicher) unterstützen, unterstützt. Für andere Dateien wird
das Erstellen eines Mappings mit diesem Schalter zu einem EOPNOTSUPP-Fehler führen.
Gemeinsame Datei-Mappings mit diesem Schalter garantieren, dass der schreibbare eingemappte
Speicheranteil im Adressraum des Prozesses auch in der gleichen Datei an dem gleichen Versatz
selbst nach einem Systemabsturz oder -neustart sichtbar ist. Im Zusammenhang mit dem Einsatz
geeigneter CPU-Anweisungen stellt dieses Benutzern solcher Mappings eine effizientere Art bereit,
solche Datenveränderungen dauerhaft zu machen.
MAP_UNINITIALIZED (seit Linux 2.6.33)
Die anonymen Seiten nicht bereinigen. Dieser Schalter ist für die Verbesserung der Leistung auf
eingebetteten Systemen gedacht. Dieser Schalter wird nur berücksichtigt, falls der Kernel mit der
Option CONFIG_MMAP_ALLOW_UNINITIALIZED konfiguriert worden war. Aufgrund der
Sicherheitsauswirkungen wird diese Option normalerweise nur auf eingebetteten Geräten (d.h.
Geräten, bei denen komplette Kontrolle über die Speicherinhalte besteht) aktiviert.
Von den obigen Schaltern ist nur MAP_FIXED in POSIX.1-2001 und POSIX.1-2008 spezifiziert. Allerdings
unterstützen die meisten Systeme MAP_ANONYMOUS (oder sein Synonym MAP_ANON).
munmap()
Der munmap-Systemaufruf hebt die Mappings im angegebenen Speicherbereich auf. Zukünftige Zugriffe auf
diesen Adressraum erzeugen dann einen Fehler vom Typ »invalid memory reference« - Ungültiger
Speicherzugriff. Der Adressraum wird außerdem automatisch ausgemappt, wenn der Prozess beendet wird. Das
Schließen des Dateideskriptors hingegen führt nicht dazu, dass der Adress-Mapping aufgehoben wird.
Die Adresse Adr muss ein Vielfaches der Seitengröße sein (für laenge ist das nicht der Fall). Alle
Seiten, die einen Teil des angezeigten Bereichs enthalten, werden ausgemappt, und nachfolgende Referenzen
auf diese Seiten führen zu SIGSEGV. Es ist kein Fehler, falls der angezeigte Bereich keine gemappten
Seiten enthält.
RÜCKGABEWERT
Bei Erfolg gibt mmap einen Zeiger auf den gemappten Speicherbereich zurück. Bei Fehlern wird MAP_FAILED
((void *) -1) zurückgegeben und errno gesetzt, um den Fehler anzuzeigen.
Bei Erfolg liefert munmap() 0 zurück. Im Fehlerfall liefert es -1 und errno wird gesetzt, um den Fehler
(wahrscheinlich EINVAL) anzuzeigen.
FEHLER
EACCES Ein Dateideskriptor bezieht sich auf eine nicht normale Datei. Oder ein Datei-Mapping wurde
angefordert, aber dd ist nicht zum Lesen geöffnet. Oder MAP_SHARED wurde erbeten und PROT_WRITE
ist gesetzt, aber dd ist nicht zum Lesen/Schreiben geöffnet (O_RDWR). Oder PROT_WRITE ist
angegeben, aber die Datei darf nur am Ende weiter beschrieben werden (»append-only«).
EAGAIN Die Datei wurde gesperrt oder zuviel Speicher wurde gesperrt (siehe setrlimit(2)).
EBADF dd ist kein gültiger Dateideskriptor (und MAP_ANONYMOUS wurde nicht gesetzt).
EEXIST MAP_FIXED_NOREPLACE wurde in Schalter angegeben und der durch Adr und laenge abgedeckte Bereich
überschneidet sich mit einem bestehenden Mapping.
EINVAL Die Adressen, die durch Adr, laenge oder Versatz angegeben wurden, sind ungültig. (Z.B. sind sie
zu groß oder nicht an einer Speicherseitengröße ausgerichtet.)
EINVAL (seit Linux 2.6.12) laenge war 0.
EINVAL Schalter enthielt weder MAP_PRIVATE, MAP_SHARED noch MAP_SHARED_VALIDATE.
ENFILE Die systemweite Beschränkung für die Gesamtzahl offener Dateien wurde erreicht.
ENODEV Das zugrundeliegende Dateisystem der angegebenen Datei unterstützt das Speicher-Mapping nicht.
ENOMEM Es ist kein Speicher verfügbar.
ENOMEM Die maximale Anzahl von Mappings des Prozesses würde überschritten. Dieser Fehler kann auch für
munmap() beim Aufheben von Mappings einer Region in der Mitte eines bestehenden Mappings
auftreten, da dies zu zwei kleineren Mappings auf jeder Seite des entmappten Bereichs führt.
ENOMEM (seit Linux 4.7). Die Prozessbeschränkung RLIMIT_DATA, beschrieben in getrlimit(2), würde
überschritten.
ENOMEM Wir mögen Adr nicht, da es den virtuellen Adressraum der CPU überschreitet.
EOVERFLOW
Auf 32-Bit-Architekturen zusammen mit den Erweiterungen für große Dateien (d.h. der Verwendung von
64-Bit off_t): die Anzahl der für laenge sowie die Anzahl der für Versatz verwandten Seiten würde
einen Überlauf von unsigned long (32-Bit) hervorrufen.
EPERM Das Argument prot verlangt PROT_EXEC, aber der gemappte Bereich gehört zu einer Datei auf einem
Dateisystem, das ohne Ausführrechte eingehängt wurde (»no-exec«).
EPERM Die Aktion wurde durch eine Dateiversiegelung verhindert; siehe fcntl(2).
EPERM Der Schalter MAP_HUGETLB wurde angegeben, aber der Aufrufende war nicht privilegiert (verfügte
nicht über die Capability CAP_IPC_LOCK) und ist kein Mitglied der Gruppe sysctl_hugetlb_shm_group;
siehe die Beschreibung von /proc/sys/vm/sysctl_hugetlb_shm_group in proc_sys(5).
ETXTBSY
MAP_DENYWRITE wurde angegeben, aber das durch dd bezeichnete Objekt ist zum Schreiben geöffnet.
Die Verwendung eines gemappten Bereichs kann diese Signale verursachen:
SIGSEGV
Es wurde versucht, in einen Bereich zu schreiben, der nur lesbar gemappt wurde.
SIGBUS Es wurde versucht, auf eine Seite des Puffers zuzugreifen, die hinter dem Ende der gemappten Datei
liegt. Für eine Erläuterung der Behandlung von Bytes in der Seite, die dem Ende der gemappten
Datei entspricht, die kein Vielfaches der Seitengröße ist, siehe ANMERKUNGEN.
ATTRIBUTE
Siehe attributes(7) für eine Erläuterung der in diesem Abschnitt verwandten Ausdrücke.
┌───────────────────────────────────────────────────────────────────┬───────────────────────┬───────────┐
│ Schnittstelle │ Attribut │ Wert │
├───────────────────────────────────────────────────────────────────┼───────────────────────┼───────────┤
│ mmap(), munmap() │ Multithread-Fähigkeit │ MT-Sicher │
└───────────────────────────────────────────────────────────────────┴───────────────────────┴───────────┘
VERSIONEN
Auf einigen Hardware-Architekturen (z.B. i386) impliziert PROT_WRITE PROT_READ. Es ist
architekturabhängig, ob PROT_READ PROT_EXEC impliziert (oder nicht). Portable Programme sollten immer
PROT_EXEC setzen, falls sie vorhaben, Code in dem neuen Mapping auszuführen.
Die portierbare Art, ein Mapping zu erstellen, ist die Angabe von Adr als 0 (NULL) und das Auslassen von
MAP_FIXED aus Schalter. In diesem Fall wählt das System die Adresse für das Mapping; die Adresse wird so
gewählt, dass sie mit keinem bestehenden Mapping in Konflikt steht und nicht 0 sein wird. Falls der
Schalter MAP_FIXED angegeben und Adr 0 (NULL) ist, dann wird die gemappte Adresse 0 (NULL) sein.
Bestimmte Schalter-Konstanten sind nur definiert, falls die geeigneten Feature-Test-Makros definiert sind
(möglicherweise standardmäßig): _DEFAULT_SOURCE mit Glibc 2.19 oder neuer; oder _BSD_SOURCE oder
_SVID_SOURCE in Glibc 2.19 und älter. (Es reicht auch aus, _GNU_SOURCE einzusetzen, und dieses Makro zu
verlangen, wäre logischer gewesen, da alle diese Schalter Linux-spezifisch sind). Die relevanten Schalter
sind: MAP_32BIT, MAP_ANONYMOUS (und das Synonym MAP_ANON), MAP_DENYWRITE, MAP_EXECUTABLE, MAP_FILE,
MAP_GROWSDOWN, MAP_HUGETLB, MAP_LOCKED, MAP_NONBLOCK, MAP_NORESERVE, MAP_POPULATE und MAP_STACK.
Unterschiede C-Bibliothek/Kernel
Diese Seite beschreibt die durch den mmap()-Wrapper der Glibc bereitgestellte Funktion. Ursprünglich rief
diese Funktion einen Systemaufruf mit dem gleichen Namen auf. Seit Linux 2.4 wurde dieser Systemaufruf
durch mmap2(2) ersetzt und heutzutage ruft die Wrapperfunktion mmap() der Glibc mmap2(2) mit einem
geeignet angepassten Wert für Versatz auf.
STANDARDS
POSIX.1-2008.
GESCHICHTE
POSIX.1-2001, SVr4, 4.4BSD.
Auf POSIX-Systemen, auf denen mmap(), msync(2) und munmap() verfügbar sind, ist _POSIX_MAPPED_FILES in
<unistd.h> auf einen Wert größer 0 definiert. (Siehe auch sysconf(3).)
ANMERKUNGEN
Speicher, der mit mmap() gemappt wurde, wird über fork(2) hinweg mit den gleichen Attributen erhalten.
Eine Datei wird in Vielfachen der Seitengröße gemappt. Für eine Datei, die nicht ein Vielfaches der
Seitengröße ist, werden die verbliebenen Bytes in der unvollständigen Seite am Ende des Mappings beim
Mappen mit Nullen überschrieben und Änderungen an diesem Bereich werden nicht in die Datei geschrieben.
Es ist nicht spezifiziert, wie sich die Größenänderung der zugrundeliegenden Datei auf das Mapping der
Seiten, die hinzugefügten oder entfernten Regionen der Datei entsprechen, auswirkt.
Durch Verwendung von mincore(2) kann eine Anwendung ermitteln, welche Seiten eines Mappings sich derzeit
im Puffer/Seitenzwischenspeicher befinden.
MAP_FIXED sicher benutzen
Der einzige sichere Anwendungsfall für MAP_FIXED ist, falls der durch Adr und laenge festgelegte
Adressbereich vorher durch ein anderes Mapping reserviert wurde; andernfalls ist die Verwendung von
MAP_FIXED gefährlich, da sie bereits bestehende Mappings zwangsweise entfernt, wodurch es für einen
Prozess mit mehreren Threads leicht wird, seinen eigenen Adressraum zu beschädigen.
Nehmen wir beispielsweise an, dass Thread A /proc/PID/maps durchsucht, um einen nicht benutzten
Adressbereich zu finden, den er mittels MAP_FIXED mappen kann, während Thread B gleichzeitig Teile des
gleichen Adressbereichs (oder den gesamten Adressbereich) erlangt. Wenn Thread A anschließend
mmap(MAP_FIXED) einsetzt, wird es das Mapping, das Thread B erstellte, durcheinanderbringen. In diesem
Szenario muss Thread B nicht das Mapping direkt erstellen: einfach ein Aufruf einer Bibliotheksfunktion,
die intern dlopen(3) zum Laden einer anderen dynamische Bibliothek verwendet, reicht aus. Der Aufruf von
dlopen(3) wird die Bibliothek in den Adressraum des Prozesses einmappen. Desweiteren kann fast jeder
Bibliotheksaufruf auf eine Art implementiert sein, die Speicher-Mappings zu dem Adressraum hinzufügt,
entweder mit dieser Technik oder einfach durch Reservierung von Speicher. Beispiele sind brk(2),
malloc(3), pthread_create(3) und die PAM-Bibliotheken http://www.linux-pam.org.
Seit Linux 4.17 kann ein Multithread-Programm den Schalter MAP_FIXED_NOREPLACE verwenden, um die oben
beschriebene Gefahr zu vermeiden, dass ein Mapping an einer festen Adresse versucht wird, die nicht durch
ein bereits existierendes Mapping reserviert wurde.
Zeitstempeländerungen für Datei-basierte Mappings
Für Datei-basierte Mappings wird das Feld st_atime für die gemappte Datei zu jedem Zeitpunkt zwischen
mmap() und dem entsprechenden Entmappen aufgerufen werden; die erste Referenz auf die gemappte Seite wird
das Feld aktualisieren, falls es nicht bereits erfolgt ist.
Das Feld st_ctime und st_mtime für eine mit PROT_WRITE und MAP_SHARED gemappte Datei wird nach einem
Schreibzugriff auf den gemappten Bereich und vor dem nachfolgenden msync(2) mit den Schalter MS_SYNC oder
MS_ASYNC, falls dieser erfolgt, aktualisiert.
Mappings großer Speicherseiten (Huge TLB)
Für Mappings, die große Speicherseiten einsetzen, unterscheiden sich die Anforderungen für die Argumente
von mmap() und munmap() etwas von den Anforderungen für Mappings, die die native Systemseitengröße
verwenden.
Für mmap() muss Versatz ein Vielfaches der unterliegenden Größe der großen Speicherseiten sein. Das
System richtet laenge automatisch aus, dass es ein Vielfaches der unterliegenden Größe der großen
Speicherseiten ist.
Für munmap() müssen sowohl Adr als auch laenge ein Vielfaches der unterliegenden Größe der großen
Speicherseiten sein.
FEHLER
Unter Linux gibt es keine Garantien, wie die, die unter MAP_NORESERVE vorgeschlagen werden. Standardmäßig
kann jeder Prozess jederzeit getötet werden, wenn dem System der Speicher ausgeht.
Vor Linux 2.6.7 hatte der Schalter MAP_POPULATE nur einen Effekt, falls prot als PROT_NONE festgelegt
ist.
SUSv3 spezifiziert, dass mmap() fehlschlagen soll, falls laenge 0 ist. Vor Linux 2.6.12 war mmap() in
diesem Fall allerdings erfolgreich: es wurde kein Mapping erstellt und der Aufruf lieferte Adr zurück.
Seit Linux 2.6.12 schlägt es in diesem Fall mit dem Fehler EINVAL fehl.
POSIX spezifiziert, dass das System immer jede teilweise gefüllte Seite am Ende des Objektes mit Nullen
auffüllen muss und dass das System niemals Änderungen an dem Objekt hinter seinem Ende schreibt. Unter
Linux verbleiben sämtliche geschriebenen Daten in solchen Teilseiten nach dem Ende des Objektes im
Seitenzwischenspeicher, selbst nachdem die Datei geschlossen und entmappt wurde und selbst obwohl die
Daten niemals zu der Datei selbst geschrieben wurden, könnten nachfolgende Mappings die veränderten
Inhalte sehen. In einigen Fällen könnte dies durch einen Aufruf von msync(2), bevor das Aufheben des
Mappings stattfindet, behoben werden, allerdings funktioniert dies nicht auf tmpfs(5) (beispielsweise
beim Einsatz der POSIX-Schnittstelle für gemeinsamen Speicher, wie in shm_overview(7) dokumentiert).
BEISPIELE
Das nachfolgende Programm gibt Teile der als sein erstes Befehlszeilenargument übergebenen Datei auf die
Standardausgabe aus. Der ausgegebene Byte-Bereich wird mittels des Versatzes und des Längenwertes im
zweiten und dritten Befehlszeilenargument angegeben. Das Programm erstellt ein Speicher-Mapping der
benötigten Seiten der Datei und verwendet write(2), um die gewünschten Bytes auszugeben.
Programmquelltext
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int
main(int argc, char *argv[])
{
int fd;
char *addr;
off_t offset, pa_offset;
size_t length;
ssize_t s;
struct stat sb;
if (argc < 3 || argc > 4) {
fprintf(stderr, "%s Dateiversatz [Länge]\n", argv[0]);
exit(EXIT_FAILURE);
}
fd = open(argv[1], O_RDONLY);
if (fd == -1)
handle_error("open");
if (fstat(fd, &sb) == -1) /* Um die Dateigröße zu erhalten */
handle_error("fstat");
offset = atoi(argv[2]);
pa_offset = offset & ~(sysconf(_SC_PAGE_SIZE) - 1);
/* Versatz für mmap() muss an der Seite ausgerichtet sein */
if (offset >= sb.st_size) {
fprintf(stderr, "Versatz ist hinter dem Dateiende\n");
exit(EXIT_FAILURE);
}
if (argc == 4) {
length = atoi(argv[3]);
if (offset + length > sb.st_size)
length = sb.st_size - offset;
/* Bytes hinter dem Dateiende können nicht angezeigt werden */
} else { /* Kein Längen-Argument ==> Anzeige bis zum Dateiende */
length = sb.st_size - offset;
}
addr = mmap(NULL, length + offset - pa_offset, PROT_READ,
MAP_PRIVATE, fd, pa_offset);
if (addr == MAP_FAILED)
handle_error("mmap");
s = write(STDOUT_FILENO, addr + offset - pa_offset, length);
if (s != length) {
if (s == -1)
handle_error("write");
fprintf(stderr, "Schreiben unvollständig");
exit(EXIT_FAILURE);
}
munmap(addr, length + offset - pa_offset);
close(fd);
exit(EXIT_SUCCESS);
}
SIEHE AUCH
ftruncate(2), getpagesize(2), memfd_create(2), mincore(2), mlock(2), mmap2(2), mprotect(2), mremap(2),
msync(2), remap_file_pages(2), setrlimit(2), shmat(2), userfaultfd(2), shm_open(3), shm_overview(7)
Die Beschreibung der folgenden Dateien in proc(5): /proc/PID/maps, /proc/PID/map_files und
/proc/PID/smaps.
B.O. Gallmeister, POSIX.4, O'Reilly, Seiten 128–129 und 389–391.
ÜBERSETZUNG
Die deutsche Übersetzung dieser Handbuchseite wurde von Johnny Teveßen <j.tevessen@gmx.de>, Martin
Schulze <joey@infodrom.org>, Dr. Tobias Quathamer <toddy@debian.org> und Helge Kreutzmann
<debian@helgefjell.de> 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 die
Mailingliste der Übersetzer: debian-l10n-german@lists.debian.org.
Linux man-pages 6.9.1 15. Juni 2024 mmap(2)