13 Stimmen

Kopiert mmap wirklich Daten in den Speicher?

Es wird gesagt, dass mmap() Dateien in den Speicher abbildet und dabei den virtuellen Adressraum des aufrufenden Prozesses benötigt. Kopiert es tatsächlich Daten in den Speicher oder existieren die Daten weiterhin auf der Festplatte? Ist mmap() schneller als read()?

42voto

Dietrich Epp Punkte 193178

Das einzige, was die Funktion mmap wirklich tut, ist einige Kernel-Datenstrukturen zu ändern und möglicherweise die Seitentabelle. Tatsächlich wird dabei überhaupt nichts in den physischen Speicher geschrieben. Nachdem Sie mmap aufgerufen haben, zeigt der allokierte Bereich wahrscheinlich nicht einmal auf den physischen Speicher: Wenn darauf zugegriffen wird, wird ein Seitenfehler verursacht. Dieser Art von Seitenfehler wird vom Kernel transparent behandelt, tatsächlich ist dies eine der Hauptaufgaben des Kernels.

Bei mmap bleibt die Daten auf der Festplatte und wird von dort in den Speicher kopiert, wenn Ihr Prozess darauf zugreift. Es kann auch spekulativ in den physischen Speicher kopiert werden. Wenn Ihr Prozess ausgelagert wird, müssen die Seiten im mmap-Bereich nicht in den Swap geschrieben werden, da sie bereits von einem langfristigen Speicher unterstützt werden - es sei denn, Sie haben sie natürlich geändert.

Allerdings belegt mmap virtuellen Adressraum, genau wie malloc und andere ähnliche Funktionen (die hauptsächlich mmap im Hintergrund verwenden, oder sbrk, was im Grunde eine spezielle Version von mmap ist). Der Hauptunterschied zwischen der Verwendung von mmap zum Lesen einer Datei und read zum Lesen einer Datei ist, dass unveränderte Seiten in einem mmap-Bereich nicht zum allgemeinen Speicherdruck beitragen, sie sind fast "kostenlos", speichermäßig gesehen, solange sie nicht verwendet werden. Im Gegensatz dazu tragen Dateien, die mit der Funktion read gelesen werden, immer zum Speicherdruck bei, unabhängig davon, ob sie verwendet oder geändert wurden.

Zu guter Letzt ist mmap gegenüber read nur in den begünstigten Anwendungsfällen - zufälliger Zugriff und Seitennutzung - schneller. Für das lineare Durchlaufen einer Datei, insbesondere einer kleinen Datei, wird read in der Regel schneller sein, da es keine Änderungen an den Seitentabellen erfordert und weniger Systemaufrufe benötigt.

Als Empfehlung kann ich sagen, dass jede große Datei, die Sie durchsuchen werden, auf 64-Bit-Systemen im Allgemeinen mit mmap und auf 32-Bit-Systemen in Teilen gemappt werden sollte, da der virtuelle Speicher dort weniger verfügbar ist.

Siehe auch: mmap() vs. reading blocks

Siehe auch (Dank an James): When should I use mmap for file access?

2voto

Alexey Frunze Punkte 59460

Die Daten sind immer noch auf der Festplatte vorhanden. Das Betriebssystem allokiert etwas physischen Speicher und kopiert die Dateidaten dorthin, damit Sie auf den Dateiinhalt zugreifen können (das geschieht, wenn Sie versuchen, auf Dateidaten zuzugreifen). Dieser physische Speicher wird in den virtuellen Adressraum des Prozesses abgebildet. Das Betriebssystem kann lange ungenutzte Teile der Datei abmappen und sie bei Bedarf wieder abmappen. Wenn nur wenig freier physischer Speicher vorhanden ist, können Abmappungen aggressiver sein und zu einer schlechten Leistung führen.

Speicherabbildung von Dateien:

  1. verwendet weniger physischen Speicher und virtuellen Adressraum als einfache "Dateilese-/schreib"-Vorgänge, weil es hier und da keine Dateipuffer gibt (im Betriebssystem, in der C-Standardbibliothek und in Ihrem Programm) und kein unnötiges Kopieren zwischen ihnen.

  2. kann (und wahrscheinlich ist es, wenn Sie genügend freien physischen Speicher haben unter bestimmten Bedingungen, je nachdem, wie viel Daten wir sprechen und wie viel physischen Speicher das Betriebssystem uns für mmap'ing zur Verfügung stellt) schneller sein als einfache "Dateilese-/schreib"-Vorgänge aufgrund des oben Genannten und weil Sie Übergänge zwischen den Benutzer- und Kernel-Modi vermeiden, die der "Dateilese"-Systemaufruf mit sich bringt. Die einzigen verbleibenden Übergänge sind diejenigen, um eine bestimmte Seite abzubilden, die derzeit nicht abgebildet ist. Diese werden durch Seitenausnahmen verursacht (=CPU-Ausnahmen), die im Kernel behandelt werden. Solange alles, was Sie benötigen, abgebildet ist, gibt es keine Benutzer-Kernel-Übergänge beim Zugriff auf Dateidaten.

2voto

Jan Hudec Punkte 69126

"Virtueller Speicher" eines Prozesses ist der Bereich der für ihn verfügbaren Adressen. Um etwas im Speicher verfügbar zu machen, müssen Sie einen Adressbereich reservieren, daher belegt mmap() einen Teil des virtuellen Speichers.

Unter Linux (und wahrscheinlich verwenden viele andere Systeme einen ähnlichen Mechanismus) wird beim Lesen einer Datei der Inhalt zunächst in vom Kernel allokierten Speicher (bei Linux ist dies der "Seitencache") geladen. Verwenden Sie dann mmap(), wird dieser Speicher dem Prozess einfach durch Zuweisen einer Adresse im Adressraum dieses Prozesses zur Verfügung gestellt. Verwenden Sie read(), allokiert der Prozess einen Puffer, der sowohl Adressen (virtueller Speicher) als auch einen Ort zum Leben (physischer Speicher) benötigt, und die Daten werden aus dem Seitencache in diesen Puffer kopiert (mehr physischer Speicher ist erforderlich).

Die Daten werden nur von der Festplatte gelesen, wenn sie tatsächlich zugegriffen werden. Im Fall von mmap() bedeutet dies, wenn Sie tatsächlich auf den Speicher zugreifen, bei read() erfolgt dies durch das Kopieren in Ihren Puffer, also innerhalb des read()-Aufrufs.

Daher ist mmap() effizienter für große Dateien, insbesondere für zufälligen Zugriff. Die Nachteile sind, dass es nur für Dateien und nicht dateiähnliche Objekte (Pipes, Sockets, Geräte, /proc-Dateien usw.) verwendet werden kann und dass ein E/A-Fehler beim Seitenfehler erkannt wird, der schwer zu handhaben ist (er sendet ein SIGBUS-Signal), während read einen Fehler zurückgeben kann und die Anwendung versuchen kann, sich zu erholen (die meisten tun es sowieso nicht). Letzteres betrifft hauptsächlich Netzdateisysteme, bei denen ein E/A-Fehler aufgrund einer verlorenen Verbindung auftreten kann.

1voto

unwind Punkte 377331

Kopieren bedeutet nicht, dass das Original zerstört wird.

Es mapped den Inhalt der Festplatte in den Speicher, also müssen die Bits natürlich irgendwann kopiert werden.

Und da dies bedeutet, dass es Adressraum benötigt, nimmt es einen Teil des virtuellen Adressraums des Prozesses ein.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X