Wann sollte ich mmap für den Dateizugriff?
Frage
POSIX-Umgebungen bieten auf mindestens zwei Arten von Dateien zugreifen. Es gibt die Standard-Systemaufrufe open()
, read()
, write()
sowie Freunde, aber es gibt auch die Möglichkeit, mmap()
unter Verwendung der Datei in den virtuellen Speicher abzubilden.
Wann ist es vorzuziehen, einen über den anderen zu bedienen? Was sind ihre individuellen Vorteilen, die Verdienst einschließlich zwei Schnittstellen?
Lösung
mmap ist groß, wenn Sie mehrere Prozesse Zugriff auf Daten in einer Nur-Lese-Mode aus der gleichen Datei haben, die in der Art von Server-Systemen üblich ist ich schreibe. mmap können alle diese Prozesse die gleichen physikalischen Speicherseiten teilen, viel Speicher zu speichern.
Mmap ermöglicht auch die Betriebssystem-Paging-Operationen zu optimieren. Betrachten wir zum Beispiel zwei Programme; Programm A, das in einer 1 MB-Datei in einen Puffer mit malloc Schaffung liest, und das Programm B, die die 1MB Datei in den Speicher mmaps. Wenn das Betriebssystem Teil A Speicher aus tauschen hat, muss er den Inhalt des Puffers schreiben zu tauschen, bevor es die Speicher wiederverwenden kann. In B Fall irgendwelche unmodifizierten mmap'd Seiten können sofort wieder verwendet werden, da das Betriebssystem weiß, wie sie aus der bestehenden Datei wiederherzustellen, sie aus mmap'd wurden. (Das Betriebssystem kann durch zunächst Markierung beschreibbaren mmap'd Seiten, welche Seiten sind unmodifizierte erkennen als nur lesen und Fehler seg kontrollieren, ähnlich zu schreiben Strategie kopieren).
mmap ist auch nützlich für die Inter-Prozess-Kommunikation. Sie können eine Datei als Lese mmap / in den Prozessen schreiben, die Synchronisations-Primitiven in der mmap'd Region kommunizieren müssen und dann verwenden (das ist, was die MAP_HASSEMAPHORE Flagge ist für).
Ein Ort Mmap kann umständlich sein, wenn man mit sehr großen Dateien auf einem 32-Bit-Maschine arbeiten müssen. Dies liegt daran, mmap hat einen zusammenhängenden Block von Adressen zu finden in Adressraum Ihres Prozesses ist, der groß genug ist, um die gesamte Bandbreite der Datei paßt abgebildet werden. Dies kann zu einem Problem werden, wenn Ihr Adressraum fragmentiert wird, wo man 2 GB Adressraum frei haben könnte, aber kein einzelner Bereich davon kann eine 1 GB Dateizuordnung passen. In diesem Fall können Sie die Datei in kleinere Stücke kartieren, als Sie es fit machen möchten.
Eine weitere potenzielle Ungeschicklichkeit mit mmap als Ersatz für Lese- / Schreib ist, dass Sie Ihre Zuordnung auf Offsets der Seitengröße beginnen. Wenn Sie nur einige Daten bei Offset X erhalten möchten, müssen Sie, dass es so kompatibel Offset fixup mit mmap.
Und schließlich lesen / schreiben sind der einzige Weg, können Arbeit mit einigen Arten von Dateien. mmap kann nicht auf Dinge wie Rohre und ttys verwendet werden.
Andere Tipps
Ein Bereich, wo ich mmap () gefunden kein Vorteil zu sein, als kleine Dateien zu lesen (unter 16 KB). Der Overhead des Seitenfehlers die gesamte Datei zu lesen war sehr hoch im Vergleich mit nur einen einzigen Lese () Systemaufruf zu tun. Das ist, da der Kernel manchmal eine Lese ganz in Ihrer Zeitscheibe satisify können, Ihren Code bedeutet weg schaltet nicht. Mit einem Seitenfehler, schien es wahrscheinlicher, dass ein anderes Programm würde geplant werden, so dass die Dateioperation eine höhere Latenz.
mmap
hat den Vorteil, wenn Sie auf große Dateien mit wahlfreiem Zugriff haben. Ein weiterer Vorteil ist, dass man es mit Speicheroperationen zugreifen (memcpy, Zeigerarithmetik), ohne mit dem Puffer stört. Normale E / A kann manchmal recht schwierig sein, wenn Puffer verwenden, wenn Sie Strukturen größer als Ihr Puffer haben. Der Code zu handhaben, dass oft schwierig ist, richtig zu machen, ist Mmap der Regel einfacher. Das heißt, es gibt bestimmte Fallen, wenn sie mit mmap
arbeiten.
Da die Menschen bereits erwähnt haben, ist mmap
ziemlich teuer einzurichten, so lohnt es sich, nur für eine bestimmte Größe mit (von Maschine zu Maschine variiert).
Für reine sequentielle Zugriffe auf die Datei, es ist auch nicht immer die bessere Lösung, wenn ein entsprechender Aufruf madvise
das Problem mildern kann.
Sie haben mit Ausrichtung Einschränkungen Ihrer Architektur (SPARC, itanium), mit Lese / Schreib-IO die Puffer sind oft richtig ausgerichtet ist und nicht Falle vorsichtig sein, wenn eine gegossene Zeiger Dereferenzierung.
Sie müssen auch darauf achten, dass Sie nicht außerhalb der Karte zugreifen. Es kann leicht passieren, wenn Sie String-Funktionen auf Ihrer Karte verwenden, und die Datei nicht über eine \ 0 am Ende enthalten. Es wird fast die ganze Zeit arbeiten, wenn die Dateigröße nicht ein Vielfaches der Seitengröße ist als die letzte Seite mit 0 gefüllt ist (das abgebildete Bereich ist immer in der Größe eines Vielfachen von Ihrer Seite Größe).
Neben anderen netten Antworten, ein Zitat von Linux Systemprogrammierung geschrieben von Google-Experten Robert Love:
Vorteile von
mmap( )
Dateien über
mmap( )
Manipulieren hat eine Handvoll von Vorteilen gegenüber der Standardread( )
undwrite( )
Systemaufrufe. Unter ihnen sind:
Lesen von und Schreiben auf eine Memory-Mapped-Datei die vermeidet Fremdkopie, die auftritt, wenn das
read( )
oderwrite( )
System Anrufe, wo die Daten zu und von einem User-Space-Puffer kopiert werden müssen.Neben potenziellen Seitenfehlern beim Lesen und Schreiben auf eine Memory-Mapped-Datei entsteht keinen Systemaufruf oder Kontextwechsel Overhead. Es ist so einfach, wie Zugriff auf den Speicher.
Wenn mehr Prozesse auf das gleiche Objekt in den Speicher abzubilden, werden die Daten unter allen Prozessen gemeinsam genutzt. Read-only und gemeinsame beschreibbare Zuordnungen sind in ihrer Gesamtheit geteilt; Private beschreibbaren Zuordnungen haben ihr noch nicht COW (copy-on-write) Seiten geteilt.
Ich suche um das Mapping beinhaltet trivial Zeiger Manipulationen. Es besteht keine Notwendigkeit für den
lseek( )
Systemaufruf.Aus diesen Gründen
mmap( )
ist eine kluge Wahl für viele Anwendungen.Nachteile von
mmap( )
Es gibt ein paar Punkte im Auge zu behalten, wenn
mmap( )
mit:
Speicherzuordnungen sind immer eine ganze Anzahl von Seiten in der Größe. Somit ist die Differenz zwischen der Größe der Trägerdatei und einem ganzzahlige Anzahl von Seiten wird als Schlupfspeicher „verschwendet“. Bei kleinen Dateien ein bedeutender Prozentsatz des Mappings verschwendet werden. Zum Beispiel mit 4-KB-Seiten, ein 7-Byte-Mapping Abfälle 4089 Bytes.
Die Speicherzuordnungen muss den Prozess Adressraum passen. Mit einem 32-Bit-Adressraum, eine sehr große Anzahl von unterschiedlich großen Mappings kann zu einer Fragmentierung des Adressraums zur Folge haben, macht es schwer, zu findet große freie angrenzende Regionen. Dieses Problem ist natürlich viel weniger offensichtlich mit einem Adressraum 64-Bit.
Es Overhead ist bei der Erstellung und die Speicherzuordnungen und zugehörige Datenstrukturen im Kernel aufrechterhalten wird. Dieser Aufwand ist im allgemeinen vermieden erwähnt durch die Eliminierung der Doppelkopie in Im vorhergehenden Abschnitt, insbesondere für größere und häufig zugegriffen Dateien.
Aus diesen Gründen sind die Vorteile des
mmap( )
am stärksten realisiert wenn die abgebildete Datei groß ist (und damit jeder verschwendete Raum ist ein kleines Prozentsatz des Gesamt mapping), oder wenn die Gesamtgröße des abgebildeten Datei ist teilbar durch die Seitengröße (und somit gibt es keine verschwendete Raum).
Memory Mapping hat ein Potential für einen großen Geschwindigkeitsvorteil im Vergleich zu herkömmlichen IO. Es ermöglicht das Betriebssystem die Daten aus der Quelldatei zu lesen, wie die Seiten in den Speicher abgebildeten Datei berührt werden. Dies funktioniert durch Verwerfungen Seiten zu schaffen, die das Betriebssystem erkennt und dann das Betriebssystem lädt die entsprechenden Daten aus der Datei automatisch.
Dies funktioniert auf die gleiche Weise wie der Paging-Mechanismus und in die Regel für hohe Geschwindigkeit optimiert ist, I / O von Daten auf Systemseite Grenzen zu lesen und Größen (in der Regel 4K) -. Größe für die meisten Dateisystem-Caches optimiert werden