mmap(2) System Calls Manual mmap(2) BEZEICHNUNG mmap, munmap - (un)mapt Dateien oder Gerate im Speicher BIBLIOTHEK Standard-C-Bibliothek (libc, -lc) UBERSICHT #include 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 fur Informationen uber Feature-Test-Makros-Anforderungen. BESCHREIBUNG mmap() erstellt ein neues Mapping in den virtuellen Adressraum des aufrufenden Prozesses. Die Anfangsadresse fur dieses neue Mapping wird in Adr angegeben. Das Argument laenge gibt an, welche Grosse das Mapping haben soll (dies muss grosser als 0 sein). Falls Adr NULL ist, wahlt 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 Nahe auswahlen (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 wahlt der Kernel eine neue Adresse, die den Hinweis berucksichtigen kann, aber nicht muss. Die Adresse des neuen Mappings wird als Ergebnis des Aufrufs zuruckgegeben. 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 Seitengrosse sein, die von sysconf(_SC_PAGE_SIZE) zuruckgegeben wird. Nachdem der mmap()-Aufruf zuruckgekehrt ist, kann der Dateideskriptor dd sofort geschlossen werden, ohne dass das Mapping ungultig wird. Das Argument prot beschreibt den gewunschten Speicherschutz des Mappings (und darf nicht im Widerspruch zum Offnungsmodus der Datei stehen). Es ist entweder PROT_NONE oder das bitweise ODER von einem oder mehreren der folgenden Schalter: PROT_EXEC Seiten konnen ausgefuhrt werden. PROT_READ Seiten durfen gelesen werden. PROT_WRITE Seiten durfen beschrieben werden. PROT_NONE Auf die Seiten darf nicht zugegriffen werden. Das Argument >>Schalter<< Das Argument Schalter bestimmt, ob Aktualisierungen des Mappings fur 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 fur 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, ausser dass MAP_SHARED-Mappings unbekannte Schalter in Schalter ignorieren. Im Gegensatz uberpruft der Kernel, wenn er Mappings mittels MAP_SHARED_VALIDATE erstellt, dass alle ubergebenen Schalter bekannt sind und schlagt mit dem Fehler EOPNOTSUPP bei unbekannten Schaltern fehl. Dieser Mapping-Typ wird auch benotigt, um bestimmte Mapping-Schalter (z.B. MAP_SYNC) verwenden zu konnen. MAP_PRIVATE Erstellt ein privates, beim Kopieren zu schreibendes Mapping. Aktualisierungen an dem Mapping sind fur andere Prozesse, die die gleiche Datei mappen, nicht sichtbar, und werden nicht an die zugrundeliegende Datei weitergeleitet. Es ist nicht spezifiziert, ob Anderungen 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. Zusatzlich konnen null oder mehrere der folgenden Werte mit OR in Schalter hinzugefugt 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 fur 64-Bit-Programme unterstutzt. Er wurde hinzugefugt, damit Thread-Stacks irgendwo innerhalb der ersten 2 GB Speicher zugewiesen werden konnen, damit die Leistung des Kontext-Umschaltens auf einigen der ersten 64-Bit-Prozessoren erhoht wird. Moderne X86-64-Prozessoren haben dieses Leistungsproblem nicht mehr, wodurch der Einsatz dieses Schalters auf diesen Systemen nicht mehr benotigt wird. Der Schalter MAP_32BIT wird ignoriert, wenn MAP_FIXED gesetzt ist. MAP_ANON Synonym fur MAP_ANONYMOUS; zur Kompatibilitat 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 Unterstutzung fur MAP_ANONYMOUS mit MAP_SHARED wurde in Linux 2.4 hinzugefugt. MAP_DENYWRITE Dieser Schalter wird ignoriert. (Vor langer Zeit - Linux 2.0 und alter - 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 Kompatibilitatsschalter. 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 Seitengrosse aus, allerdings konnten einige Architekturen zusatzliche Anforderungen stellen. Falls der mit Adr und laenge festgelegte Speicherbereich bestehende Mappings uberlappt, dann wird der uberlappende 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 berucksichtigen, dass sich die genaue Anordnung der Mappings des Prozesses im Speicher deutlich zwischen Linuxversionen, C-Bibliotheksversionen und Betriebssystemveroffentlichungen unterscheiden kann. Lesen Sie die Erorterung dieses Schalters im Abschnitt ANMERKUNGEN sorgfaltig! MAP_FIXED_NOREPLACE (seit Linux 4.17) Dieser Schalter stellt ein Verhalten bereit, das MAP_FIXED im Hinblick auf die Erzwingung von Adr ahnelt, sich aber dadurch unterscheidet, dass MAP_FIXED_NOREPLACE einen bereits bestehenden, gemappten Bereich durcheinanderbringt. Falls der angeforderte Bereich mit einem bestehenden Mapping kollidieren wurde, dann schlagt dieser Aufruf mit EEXIST fehl. Dieser Schalter kann daher fur 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 altere 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<< zuruckfallen: sie liefern eine Adresse zuruck, die sich von der angeforderten Adresse unterscheidet. Daher sollte ruckwartskompatible Software die zuruckgelieferte Adresse mit der angeforderten Adresse vergleichen. MAP_GROWSDOWN Dieser Schalter wird fur Stacks verwandt. Er zeigt dem Kernelsystem fur virtuellen Speicher an, dass sich das Mapping nach unten im Speicher ausdehnen soll. Die zuruckgelieferte Adresse ist eine Seite tiefer als der Speicherbereich, der tatsachlich im virtuellen Adressraum des Prozesses erstellt wird. Wird eine Adresse in der >>Wachter<<-Seite unterhalb des Mappings beruhrt, dann wachst das Mapping um eine Seite. Dieses Wachstum kann wiederholt werden, bis das Mapping bis auf eine Seite innerhalb des hohen Endes des nachst-niedrigeren Mappings anwachst - zu diesem Zeitpunkt fuhrt das Beruhren der >>Wachter<<-Seite zu einem SIGSEGV-Signal. MAP_HUGETLB (seit Linux 2.6.32) Reserviert das Mapping mittels >>grosser<< Speicherseiten. Siehe die Linux-Kernelquelldatei Documentation/admin-guide/mm/hugetlbpage.rst sowie die nachfolgenden ANMERKUNGEN fur weitere Details. MAP_HUGE_2MB MAP_HUGE_1GB (seit Linux 3.8) Wird in Zusammenhang mit MAP_HUGETLB verwandt, um alternative hugetlb-Seitengrossen (respektive 2 MB und 1 GB) auf Systemen auszuwahlen, die mehrere hugetlb-Seitengrossen unterstutzen. Allgemeiner kann die gewunschte Grosse der grossen Speicherseiten durch Kodierung des Logarithmus zur Basis 2 der gewunschten Seitengrosse in den sechs Bits am Versatz MAP_HUGE_SHIFT konfiguriert werden. (Ein Wert 0 in diesem Bitfeld stellt die standardmassige grosse Speicherseitengrosse bereit; die Vorgabegrosse grosser 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 unterstutzte Bereich der Grosse der grossen 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 konnen spater grosse Ausnahmebehandlungen passieren. Daher ist die Semantik nicht so stark wie mlock(2). Sie sollten mmap() mit mlock(2) verwenden, wenn grosse Ausnahmebehandlungen nach der Initialisierung des Mappings nicht akzeptierbar sind. Der Schalter MAP_LOCKED wird unter alteren Kerneln ignoriert. MAP_NONBLOCK (seit Linux 2.5.46) Dieser Schalter ergibt nur im Zusammenhang mit MAP_POPULATE Sinn. Es wird kein Vorauslesen durchgefuhrt, es werden Seitentabelleneintrage nur fur Seiten erstellt, die bereits im RAM vorhanden sind. Seit Linux 2.6.23 fuhrt dieser Schalter dazu, dass MAP_POPULATE nichts macht. Irgendwann konnte die Kombination von MAP_POPULATE und MAP_NONBLOCK wieder implementiert werden. MAP_NORESERVE Reserviert fur dieses Mapping keinen Auslagerungsspeicher. Wenn Auslagerungsspeicher reserviert wird, muss garantiert werden, dass Anderungen an dem Mapping moglich sind. Wird kein Auslagerungsspeicher reserviert, konnte beim Schreiben ein SIGSEGV empfangen werden, falls kein physischer Speicher verfugbar ist. Siehe auch die Diskussion der Datei /proc/sys/vm/overcommit_memory in proc(5). Vor Linux 2.6 hatte dieser Schalter nur fur private, schreibbare Mappings eine Wirkung. MAP_POPULATE (seit Linux 2.5.46) Belegt (>>prefault<<) Seitentabellen fur ein Mapping. Fur ein Datei-Mapping fuhrt dies zu einem Vorablesen der Datei. Dies hilft dabei, spater Blockierungen bei Seitenausnahmebehandlungen zu vermeiden. Der Aufruf mmap() schlagt nicht fehl, falls das Mapping nicht belegt werden kann (beispielsweise aufgrund von Beschrankungen der Anzahl der gemappten grossen Seiten bei der Verwendung von MAP_HUGETLB). Die Unterstutzung fur MAP_POPULATE zusammen mit privaten Mappings wurde in Linux 2.6.23 hinzugefugt. MAP_STACK (seit Linux 2.6.27) Reserverviert ein Mapping an einer Adresse, die fur einen Stack eines Prozesses oder Threads geeignet ist. Dieser Schalter lost derzeit nichts aus. Durch Einsatz dieses Schalters konnen Anwendungen aber transparent sicherstellen, dass sie die Unterstutzung 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 (spater) eine besondere Behandlung von Stack-Zuweisungen notig sein konnte. Ein weiterer Grund, diesen Schalter einzusetzen, ist die Portabilitat: 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 verfugbar. Mappings vom Typ MAP_SHARED ignorieren diesen Schalter ohne Ruckmeldung. Dieser Schalter wird nur fur Dateien, die DAX (direktes Mapping von dauerhaftem Speicher) unterstutzen, unterstutzt. Fur andere Dateien wird das Erstellen eines Mappings mit diesem Schalter zu einem EOPNOTSUPP-Fehler fuhren. 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 Datenveranderungen dauerhaft zu machen. MAP_UNINITIALIZED (seit Linux 2.6.33) Die anonymen Seiten nicht bereinigen. Dieser Schalter ist fur die Verbesserung der Leistung auf eingebetteten Systemen gedacht. Dieser Schalter wird nur berucksichtigt, falls der Kernel mit der Option CONFIG_MMAP_ALLOW_UNINITIALIZED konfiguriert worden war. Aufgrund der Sicherheitsauswirkungen wird diese Option normalerweise nur auf eingebetteten Geraten (d.h. Geraten, bei denen komplette Kontrolle uber die Speicherinhalte besteht) aktiviert. Von den obigen Schaltern ist nur MAP_FIXED in POSIX.1-2001 und POSIX.1-2008 spezifiziert. Allerdings unterstutzen die meisten Systeme MAP_ANONYMOUS (oder sein Synonym MAP_ANON). munmap() Der munmap-Systemaufruf hebt die Mappings im angegebenen Speicherbereich auf. Zukunftige Zugriffe auf diesen Adressraum erzeugen dann einen Fehler vom Typ >>invalid memory reference<< - Ungultiger Speicherzugriff. Der Adressraum wird ausserdem automatisch ausgemappt, wenn der Prozess beendet wird. Das Schliessen des Dateideskriptors hingegen fuhrt nicht dazu, dass der Adress-Mapping aufgehoben wird. Die Adresse Adr muss ein Vielfaches der Seitengrosse sein (fur laenge ist das nicht der Fall). Alle Seiten, die einen Teil des angezeigten Bereichs enthalten, werden ausgemappt, und nachfolgende Referenzen auf diese Seiten fuhren zu SIGSEGV. Es ist kein Fehler, falls der angezeigte Bereich keine gemappten Seiten enthalt. RUCKGABEWERT Bei Erfolg gibt mmap einen Zeiger auf den gemappten Speicherbereich zuruck. Bei Fehlern wird MAP_FAILED ((void *) -1) zuruckgegeben und errno gesetzt, um den Fehler anzuzeigen. Bei Erfolg liefert munmap() 0 zuruck. 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 geoffnet. Oder MAP_SHARED wurde erbeten und PROT_WRITE ist gesetzt, aber dd ist nicht zum Lesen/Schreiben geoffnet (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 gultiger Dateideskriptor (und MAP_ANONYMOUS wurde nicht gesetzt). EEXIST MAP_FIXED_NOREPLACE wurde in Schalter angegeben und der durch Adr und laenge abgedeckte Bereich uberschneidet sich mit einem bestehenden Mapping. EINVAL Die Adressen, die durch Adr, laenge oder Versatz angegeben wurden, sind ungultig. (Z.B. sind sie zu gross oder nicht an einer Speicherseitengrosse 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 Beschrankung fur die Gesamtzahl offener Dateien wurde erreicht. ENODEV Das zugrundeliegende Dateisystem der angegebenen Datei unterstutzt das Speicher-Mapping nicht. ENOMEM Es ist kein Speicher verfugbar. ENOMEM Die maximale Anzahl von Mappings des Prozesses wurde uberschritten. Dieser Fehler kann auch fur 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 fuhrt. ENOMEM (seit Linux 4.7). Die Prozessbeschrankung RLIMIT_DATA, beschrieben in getrlimit(2), wurde uberschritten. ENOMEM Wir mogen Adr nicht, da es den virtuellen Adressraum der CPU uberschreitet. EOVERFLOW Auf 32-Bit-Architekturen zusammen mit den Erweiterungen fur grosse Dateien (d.h. der Verwendung von 64-Bit off_t): die Anzahl der fur laenge sowie die Anzahl der fur Versatz verwandten Seiten wurde einen Uberlauf von unsigned long (32-Bit) hervorrufen. EPERM Das Argument prot verlangt PROT_EXEC, aber der gemappte Bereich gehort zu einer Datei auf einem Dateisystem, das ohne Ausfuhrrechte eingehangt 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 (verfugte nicht uber 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 geoffnet. 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. Fur eine Erlauterung der Behandlung von Bytes in der Seite, die dem Ende der gemappten Datei entspricht, die kein Vielfaches der Seitengrosse ist, siehe ANMERKUNGEN. ATTRIBUTE Siehe attributes(7) fur eine Erlauterung der in diesem Abschnitt verwandten Ausdrucke. +--------------------------------+-------------------------+-----------+ |Schnittstelle | Attribut | Wert | +--------------------------------+-------------------------+-----------+ |mmap(), munmap() | Multithread-Fahigkeit | MT-Sicher | +--------------------------------+-------------------------+-----------+ VERSIONEN Auf einigen Hardware-Architekturen (z.B. i386) impliziert PROT_WRITE PROT_READ. Es ist architekturabhangig, ob PROT_READ PROT_EXEC impliziert (oder nicht). Portable Programme sollten immer PROT_EXEC setzen, falls sie vorhaben, Code in dem neuen Mapping auszufuhren. 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 wahlt das System die Adresse fur das Mapping; die Adresse wird so gewahlt, 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 (moglicherweise standardmassig): _DEFAULT_SOURCE mit Glibc 2.19 oder neuer; oder _BSD_SOURCE oder _SVID_SOURCE in Glibc 2.19 und alter. (Es reicht auch aus, _GNU_SOURCE einzusetzen, und dieses Makro zu verlangen, ware 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. Ursprunglich 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 fur Versatz auf. STANDARDS POSIX.1-2008. GESCHICHTE POSIX.1-2001, SVr4, 4.4BSD. Auf POSIX-Systemen, auf denen mmap(), msync(2) und munmap() verfugbar sind, ist _POSIX_MAPPED_FILES in auf einen Wert grosser 0 definiert. (Siehe auch sysconf(3).) ANMERKUNGEN Speicher, der mit mmap() gemappt wurde, wird uber fork(2) hinweg mit den gleichen Attributen erhalten. Eine Datei wird in Vielfachen der Seitengrosse gemappt. Fur eine Datei, die nicht ein Vielfaches der Seitengrosse ist, werden die verbliebenen Bytes in der unvollstandigen Seite am Ende des Mappings beim Mappen mit Nullen uberschrieben und Anderungen an diesem Bereich werden nicht in die Datei geschrieben. Es ist nicht spezifiziert, wie sich die Grossenanderung der zugrundeliegenden Datei auf das Mapping der Seiten, die hinzugefugten 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 fur 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 gefahrlich, da sie bereits bestehende Mappings zwangsweise entfernt, wodurch es fur einen Prozess mit mehreren Threads leicht wird, seinen eigenen Adressraum zu beschadigen. 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, wahrend Thread B gleichzeitig Teile des gleichen Adressbereichs (oder den gesamten Adressbereich) erlangt. Wenn Thread A anschliessend 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 hinzufugt, entweder mit dieser Technik oder einfach durch Reservierung von Speicher. Beispiele sind brk(2), malloc(3), pthread_create(3) und die PAM-Bibliotheken . 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. Zeitstempelanderungen fur Datei-basierte Mappings Fur Datei-basierte Mappings wird das Feld st_atime fur 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 fur 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 grosser Speicherseiten (Huge TLB) Fur Mappings, die grosse Speicherseiten einsetzen, unterscheiden sich die Anforderungen fur die Argumente von mmap() und munmap() etwas von den Anforderungen fur Mappings, die die native Systemseitengrosse verwenden. Fur mmap() muss Versatz ein Vielfaches der unterliegenden Grosse der grossen Speicherseiten sein. Das System richtet laenge automatisch aus, dass es ein Vielfaches der unterliegenden Grosse der grossen Speicherseiten ist. Fur munmap() mussen sowohl Adr als auch laenge ein Vielfaches der unterliegenden Grosse der grossen Speicherseiten sein. FEHLER Unter Linux gibt es keine Garantien, wie die, die unter MAP_NORESERVE vorgeschlagen werden. Standardmassig kann jeder Prozess jederzeit getotet 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 zuruck. Seit Linux 2.6.12 schlagt es in diesem Fall mit dem Fehler EINVAL fehl. POSIX spezifiziert, dass das System immer jede teilweise gefullte Seite am Ende des Objektes mit Nullen auffullen muss und dass das System niemals Anderungen an dem Objekt hinter seinem Ende schreibt. Unter Linux verbleiben samtliche 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, konnten nachfolgende Mappings die veranderten Inhalte sehen. In einigen Fallen konnte 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 fur gemeinsamen Speicher, wie in shm_overview(7) dokumentiert). BEISPIELE Das nachfolgende Programm gibt Teile der als sein erstes Befehlszeilenargument ubergebenen Datei auf die Standardausgabe aus. Der ausgegebene Byte-Bereich wird mittels des Versatzes und des Langenwertes im zweiten und dritten Befehlszeilenargument angegeben. Das Programm erstellt ein Speicher-Mapping der benotigten Seiten der Datei und verwendet write(2), um die gewunschten Bytes auszugeben. Programmquelltext #include #include #include #include #include #include #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 [Lange]\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 Dateigrosse zu erhalten */ handle_error("fstat"); offset = atoi(argv[2]); pa_offset = offset & ~(sysconf(_SC_PAGE_SIZE) - 1); /* Versatz fur 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 konnen nicht angezeigt werden */ } else { /* Kein Langen-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 unvollstandig"); 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. UBERSETZUNG Die deutsche Ubersetzung dieser Handbuchseite wurde von Johnny Tevessen , Martin Schulze , Dr. Tobias Quathamer und Helge Kreutzmann erstellt. Diese Ubersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 oder neuer bezuglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG ubernommen. Wenn Sie Fehler in der Ubersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an die Mailingliste der Ubersetzer . Linux man-pages 6.06 31. Oktober 2023 mmap(2)