Grenzen von mmap()?



  • Kennt hier jemand die maximale Grenze für die Größe von Dateien
    bei der Verwendung von glibc's mmap() Funktion unter Linux
    und zwar für...

    - ein 32-Bit System welches keinen Gebrauch von LFS
    (Large File Support) macht?
    - ein 32-Bit System welches Gebrauch von LFS macht?
    - ein 64-Bit System?

    (natürlich alles mit einem Kernel >2.6)

    Die glibc Dokumentation sagt dazu folgendes:
    "Since mmapped pages can be stored back to their file when physical
    memory is low, it is possible to mmap files orders of magnitude larger
    than both the physical memory and swap space. The only limit is address
    space. The theoretical limit is 4GB on a 32-bit machine - however, the
    actual limit will be smaller since some areas will be reserved for other
    purposes. If the LFS interface is used the file size on 32-bit systems
    is not limited to 2GB (offsets are signed which reduces the addressable
    area of 4GB by half); the full 64-bit are available."

    - I zweifel irgendwie dran, das die vollen 64-Bit (wäre irgendwas mit
    Exabyte) verfügbar sind auf jeder Maschine. Weiss jemand mehr?

    Ich hab zu dem Thema auch eine alte Mail (April 2004) in den
    Linux-Kernel Archiven gefunden:
    "There is a limit per process in the kernel vm that prevent from
    mmapping more than 512GB of data."

    - Weiss jemand ob das immer noch zutrifft für die aktuellen Kernel
    bzw. was es noch alles für Einschränkungen gibt?

    Ein Beispiel zur Verdeutlichung um was es mir geht:

    Nehmen wir an ich hab eine 8 GB Datei, 1 GB physischen Hauptspeicher
    und Ich will diese Datei mappen auf einer 32-Bit Maschine mit der
    Hilfe von LFS?

    - Ist das überhaupt möglich, laut der glibc Doku müsste das ja ohne
    Probleme funktionieren?

    Nehmen wir weiter an das ich nun 2 oder mehr Zeiger habe, welche
    auf die gemappte Datei zeigen und dauernd ihre Position ändern um
    untereinander die Daten auszutauschen, auf die sie zeigen.

    - Wie ist das möglich wenn ich nicht genug Hauptspeicher habe um die
    vollen 8 GB im Speicher zu halten? Die glibc Dokumentation redet ja hier
    von "Pages" die bei Bedarf rein- bzw. rausgemapped werden (ähnlich Swap)
    wenn ich das richtig verstehe, je nachdem was ich für Teile von der Datei
    benötige, aber ist dieser Aufwand nicht höher als eine vergleichbare
    Operation ohne mmap() und mit normalen Dateizeigern und -funktionen,
    d.h. sog. random access (lseek etc.)?

    Ich bin für jede Hilfe dankbar, auch wenns nur eine Frage beantwortet.
    Persönliche Erfahrungswerte im Zusammenhang mit mmap() sind auch
    willkommen.

    mfg
    Andreas



  • immortal schrieb:

    - Ist das überhaupt möglich, laut der glibc Doku müsste das ja ohne
    Probleme funktionieren?

    Du kannst Teile der Datei reinmappen, aber niemals die ganze, weil der Adressraum mit 32 Bit zu klein ist.

    immortal schrieb:

    - Wie ist das möglich wenn ich nicht genug Hauptspeicher habe um die
    vollen 8 GB im Speicher zu halten? Die glibc Dokumentation redet ja hier
    von "Pages" die bei Bedarf rein- bzw. rausgemapped werden (ähnlich Swap)
    wenn ich das richtig verstehe, je nachdem was ich für Teile von der Datei
    benötige, aber ist dieser Aufwand nicht höher als eine vergleichbare
    Operation ohne mmap() und mit normalen Dateizeigern und -funktionen,
    d.h. sog. random access (lseek etc.)?

    Die Größe des Hauptspeichers ist dafür nicht wirklich interessant, es scheitert einfach an der Größe des Adressraumes. Mit 32 Bit kann man prinzipiell auf 4GB zugreifen, allerdings muss man unter Linux 1GB für den Kernel abziehen, und dann braucht man noch jeweils ein bisschen was für Code/Daten/Stack/Heap. Wo jetzt die genaue Grenze liegt, weiß ich aber auch nicht genau. Der Aufwand ist nicht höher als mit den anderen Funktionen, weil sich das sehr gut durch die Paging Unit der CPU unterstützen lässt.



  • Ringding schrieb:

    Du kannst Teile der Datei reinmappen, aber niemals die ganze, weil der Adressraum mit 32 Bit zu klein ist.

    Hab ich auch gedacht, aber was bedeutet dann dieser Satz aus der glibc Doku?
    "If the LFS interface is used the file size on 32-bit systems is not limited to 2GB (offsets are signed which reduces the addressable area of 4GB by half); the full 64-bit are available."

    d.h. in meinen Augen, dass es mit dem LFS Interface zumindest möglich ist z.B. 8 GB an einem Stueck zu mappen wenn ich das hier richtig verstehe. Wie der Kernel die Sache effizient verwaltet ist für mich die interessante Frage, da ja nicht dieser Platz im RAM zur Verfügung steht.

    Ringding schrieb:

    Die Größe des Hauptspeichers ist dafür nicht wirklich interessant, es scheitert einfach an der Größe des Adressraumes. Mit 32 Bit kann man prinzipiell auf 4GB zugreifen, allerdings muss man unter Linux 1GB für den Kernel abziehen, und dann braucht man noch jeweils ein bisschen was für Code/Daten/Stack/Heap. Wo jetzt die genaue Grenze liegt, weiß ich aber auch nicht genau. Der Aufwand ist nicht höher als mit den anderen Funktionen, weil sich das sehr gut durch die Paging Unit der CPU unterstützen lässt.

    Wenn die Größe keine Rolle spielt, warum werden dann Dateien nicht grundsätzlich mit mmap() geöffnet und bearbeitet? Müsste doch eigentlich schneller sein als das normale Filepointer-Rumgeschiebe, oder?



  • - ein 32-Bit System welches keinen Gebrauch von LFS
    (Large File Support) macht?
    - ein 32-Bit System welches Gebrauch von LFS macht?
    - ein 64-Bit System

    1. 232
    2.,3. 264

    - I zweifel irgendwie dran, das die vollen 64-Bit (wäre irgendwas mit
    Exabyte) verfügbar sind auf jeder Maschine. Weiss jemand mehr?

    Wieso nicht? Ist doch nur vom physischen Speicher limitiert.

    - Weiss jemand ob das immer noch zutrifft für die aktuellen Kernel
    bzw. was es noch alles für Einschränkungen gibt?

    Irgend wie kann man die Speicherlimits glaube ich aus /proc oder /sys auslesen. Weiß jetzt aber nicht wo. Auf jeden Fall kann man die glaube ich bei der Kernelerstellung verändern

    Die glibc Dokumentation redet ja hier
    von "Pages" die bei Bedarf rein- bzw. rausgemapped werden (ähnlich Swap)

    Nein, genau das ist Swaping.

    Ich denke dein Problem ist einfach, dass du dir vorstellst, dass dein Arbeitsspeicher auf den physischen RAM beschränkt ist. Aber Pages (Speicherseiten) werden eben ständig aus dem RAM in den Swap Space kopiert und umgekehrt. Such dir vielleicht mal Artikel über modernes Speichermanagement.



  • kingruedi schrieb:

    1. 232
    2.,3. 264

    hab ich mir fast gedacht, zumindest fuer den theoretischen adressraum...

    kingruedi schrieb:

    Irgend wie kann man die Speicherlimits glaube ich aus /proc oder /sys auslesen. Weiß jetzt aber nicht wo. Auf jeden Fall kann man die glaube ich bei der Kernelerstellung verändern

    ok, das werd ich mal pruefen

    kingruedi schrieb:

    Wieso nicht? Ist doch nur vom physischen Speicher limitiert.

    Nein, genau das ist Swaping.

    Ich denke dein Problem ist einfach, dass du dir vorstellst, dass dein Arbeitsspeicher auf den physischen RAM beschränkt ist. Aber Pages (Speicherseiten) werden eben ständig aus dem RAM in den Swap Space kopiert und umgekehrt. Such dir vielleicht mal Artikel über modernes Speichermanagement.

    danke fuer die blumen, aber es ging blos um den zusammenhang und der ist jetzt klar wenn es so ablaeuft wie du schreibst

    Wenn die Größe also theoretisch keine Rolle spielt, warum werden dann Dateien nicht grundsätzlich mit mmap() geöffnet und bearbeitet? Müsste doch eigentlich schneller sein als das normale Filepointer-Rumgeschiebe, zumindest bei gewolltem wahlfreiem Zugriff, oder? Es muss doch auch nen Nachteil geben...



  • Ja.

    • Es kommt auf die Größe an - wenn du zwei 900MB-Files gemapped hast und nebenbei noch ein bisschen Heap haben willst, hast du schon ein Problem auf einem 32bit-System.
    • Ist nicht portabel.
    • Die Größe muss von vornherein bekannt sein.


  • immortal schrieb:

    Hab ich auch gedacht, aber was bedeutet dann dieser Satz aus der glibc Doku?
    "If the LFS interface is used the file size on 32-bit systems is not limited to 2GB (offsets are signed which reduces the addressable area of 4GB by half); the full 64-bit are available."

    d.h. in meinen Augen, dass es mit dem LFS Interface zumindest möglich ist z.B. 8 GB an einem Stueck zu mappen wenn ich das hier richtig verstehe. Wie der Kernel die Sache effizient verwaltet ist für mich die interessante Frage, da ja nicht dieser Platz im RAM zur Verfügung steht.

    Nein auf 32 Bit hilft dir LFS nicht um die ganze Dateireinzumappen. Dazu bräuchtest du 33-Bit-Adressen und die kann man in 32 Bit nunmal nicht darstellen. Du kannst nur auf die gesamte Datei zugreifen und entsprechend Häppchen davon reinmappen. Ohne LFS hättest du keine Chance überhaupt mehr als 2GiB von der Datei je zu sehen. Effektiv gibts also zwei Limits
    1. Das Adressraumlimit (wieviel kann ich auf einmal mmap()en?)
    2. Das Dateizugriffslimit (auf welchen Teil der Datei kann ich zugreifen?)

    Das erste wird von der Architektur und der bestehenden Belegung bestimmt, bei 32-Bit hast du 4GiB Adressraum von dem du dann je nach Kernel ca. 2-3 Gi abzüglich Stack, Heap etc. hast. Auf ner 64-Bit Architektur hast du dementsprechend 2^64 Byte.

    LFS regelt dann auf welche Bereiche der Datei du zugreifen kannst, ohne LFS nur auf die ersten 2 GiB, ansonsten auf bis zu 2^64 Byte.

    HTH



  • danke vielmals, das war genau die loesung die ich gebraucht hab...

    Ringding schrieb:

    • Ist nicht portabel.

    portabel inwiefern? wenn ich z.B. die glibc fuer win32 und linux verfuegbar hab muesste es doch funktionieren, oder? (momentan waeren fuer mich nur die 2 systeme wichtig)



  • Ich habe noch nie glibc auf win32 gesehen.



  • Ringding schrieb:

    Ich habe noch nie glibc auf win32 gesehen.

    Cygwin und Mingw sollten ansich eine haben?

    Edit: Wobei ein Google nach glibc win32 tatsächlich anderes andeutet...



  • jo, ich benutze mingw und dacht bis grad eben eigentlich auch das sie zumindest ne abgespeckte version von glibc mitliefern, aber sie scheint etwas zu sehr mit linux verzahnt zu sein als das sie sich so einfach portieren laesst.

    wird anscheinend alles auf win32 api abgebildet, d.h. wenn ich mmap() benutze muesste ich mindestens ne #ifdef WIN32 variante fuer windoof einbauen. -> schoene scheisse, aber waer net des erste mal in dem programm 🙂

    ich glaub damit haben wir das ganze soweit erstmal komplett aufgedeckt, danke nochmal.



  • Cygwin ist zB eine POSIX Implementierung für Windows. Solltest du dir vll. mal angucken, dann hast du weniger Portierungsarbeit.



  • kingruedi schrieb:

    Cygwin ist zB eine POSIX Implementierung für Windows. Solltest du dir vll. mal angucken, dann hast du weniger Portierungsarbeit.

    da hast du recht, leider liegt meine prioritaet auch etwas in kompletter standalone application ohne zusaetzliche dll's oder registry-eintraege wie ich sie z.b. bei cygwin benoetige. zudem hab ich einiges gelesen das die laufzeit mit mingw besser sein soll da es eben versucht native binaries zu bauen, aber das kann unterschliedlich sein, denn mingw is im vergleich zum msvc ja auch grottenlangsam.

    im prinzip ist beides nix gescheites, "linux only" waer des beste, da gaebs keine probleme und (fast :)) alle waeren gluecklich


Anmelden zum Antworten