2010-08-19 13 views
13

Ich versuche herauszufinden, wie Memory-Mapped-Dateien auf einem Mac neu zugeordnet werden (wenn ich den verfügbaren Speicherplatz erweitern möchte).Gibt es in Darwin wirklich keine Mrmap?

Ich sehe unsere Freunde in der Linux-Welt haben mremap, aber ich kann keine solche Funktion in den Kopfzeilen auf meinem Mac finden. /Developer/SDKs/MacOSX10.6.sdk/usr/include/sys/mman.h hat die folgenden:

  • mmap
  • mprotect
  • msync
  • munlock
  • munmap
  • aber keine mremap

man mremap bestätigt meine Ängste.

Ich bin derzeit auf munmap und mmmap, wenn ich die Größe der zugeordneten Datei Größe ändern möchte, die Invalidierung aller geladenen Seiten beinhaltet. Es muss einen besseren Weg geben. Sicherlich?

Ich versuche Code zu schreiben, der unter Mac OS X und Linux funktioniert. Ich könnte mich mit einem Makro begnügen, um die jeweils beste Funktion zu verwenden, wenn ich hätte, aber ich würde es lieber richtig machen.

Antwort

0

Sie können die Datei auf eine große Größe func- tieren (indem Sie ein Loch erstellen) und alle davon mmapen. Wenn die Datei persistent ist, empfehle ich, das Loch mit Schreibaufrufen zu füllen, anstatt in das Mapping zu schreiben, da sonst die Blöcke der Datei möglicherweise unnötig auf der Platte fragmentiert werden.

+0

Also schlägst du vor, ich sollte für die größtmögliche Größe zuweisen, die ich jemals wollen und füllen Sie das Loch? Es ist eine interessante Idee, aber entweder kartographiere ich den maximal möglichen Adressbereich und lasse keine Adressen für irgendwas anderes übrig, oder ich benutze einen kleineren Betrag und riskiere, dass ich auslaufe. Dies wäre auch nicht plattformübergreifend (wie in meiner Frage angegeben), da ich nicht garantieren konnte, dass irgendein Dateisystem tatsächlich den gesamten Bereich der Datei auf null setzen und Gigabytes verschwenden würde. – Joe

+3

Sie müssen nicht einmal die Datei auf der Festplatte so groß machen. Nur 'mmap' größer als die Dateigröße. Zugriffe nach dem Ende der Datei führen zu "SIGBUS", also müssen Sie es länger "ftrunzieren", bevor Sie versuchen, über die 'mmap' auf neue Teile zuzugreifen, aber ansonsten ist es in Ordnung. –

0

Ich habe keine Erfahrung mit Speicherzuordnung, aber es sieht so aus, als ob Sie die gleiche Datei zweimal als eine Möglichkeit, das Mapping zu erweitern, ohne etwas zu verlieren zuordnen können.

int main() { 
    int fd; 
    char *fp, *fp2, *pen; 

     /* create 1K file */ 
    fd = open("mmap_data.txt", O_RDWR | O_CREAT, 0777); 
    lseek(fd, 1000, SEEK_SET); 
    write(fd, "a", 1); 

     /* map and populate it */ 
    fp = mmap(NULL, 1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 
    pen = memset(fp, 'x', 1000); 

     /* expand to 8K and establish overlapping mapping */ 
    lseek(fd, 8000, SEEK_SET); 
    write(fd, "b", 1); 
    fp2 = mmap(NULL, 7000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 

     /* demonstrate that mappings alias */ 
    *fp = 'z'; 
    printf("%c ", *fp2); 

     /* eliminate first mapping */ 
    munmap(fp, 1000); 

     /* populate second mapping */ 
    pen = memset(fp2+10, 'y', 7000); 

     /* wrap up */ 
    munmap(fp2, 7000); 
    close(fd); 
    printf("%d\n", errno); 
} 

Der Ausgang ist zxxxxxxxxxyyyyyy.....

Ich nehme an, wenn Sie darauf stoßen, kann es möglich sein, den Adressraum schneller als mit mremap zu laufen. Aber nichts ist in beiden Richtungen garantiert und es könnte auch genauso sicher sein.

+1

Korrigieren Sie mich, wenn ich falsch liege, aber würde dies eine Menge zusätzlicher IO über mmap MAP_PRIVATE und mremap nicht verursachen? Aufgrund von MAP_SHARED-Flushing schreibt auf die Festplatte? – Eloff

+0

@Eloff: Nur so ist es zu versuchen und zu sehen. Dieser Beitrag ist sehr alt und ich hatte nie viel Anreiz, das Experiment durchzuführen: vP. Es wäre ein wenig überraschend, übermäßige Flushes zu sehen, da der gesamte Speicher immer mindestens einmal gemappt wird. Das Betriebssystem sollte nur spülen, wenn das letzte Mapping beseitigt ist, oder? – Potatoswatter

5

Wenn Sie die Karte verkleinern müssen, nur munmap der Teil am Ende, den Sie entfernen möchten.

Wenn Sie die Karte vergrößern müssen, können Sie den richtigen Offset mit MAP_FIXED an die Adressen direkt über der alte Karte mmap, aber Sie müssen vorsichtig sein, dass Sie nicht über etwas ordnen anderes, das bereits vorhanden ist ..

Der obige Text unter strikeout ist eine schreckliche Idee; MAP_FIXED ist grundsätzlich falsch, wenn Sie bereits wissen, was an der Zieladresse ist und es atomar ersetzen möchten. Wenn Sie versuchen, etwas opportunistisch etwas neu zuzuordnen, wenn der Adressbereich frei ist, müssen Sie mmap mit einer angeforderten Adresse aber ohneMAP_FIXED verwenden und sehen, ob es erfolgreich ist und Ihnen die angeforderte Adresse gibt; Wenn es erfolgreich ist, aber mit einer anderen Adresse, müssen Sie die neue Zuordnung, die Sie gerade erstellt haben, aufheben und davon ausgehen, dass die Zuweisung an die angeforderte Adresse nicht möglich war.

+0

Führt das Hinzufügen einer zusätzlichen zugeordneten Region nicht zu dem Risiko, dass sie nicht an dieser Adresse zugewiesen werden kann? – Joe

+0

Ja, darüber habe ich gewarnt. Aber ich glaube, MAP_FIXED wird immer über einem bestehenden Mapping (das bestehende Mapping wird zerstört) abbilden anstatt zu scheitern, was noch schlimmer ist. –

1

Wenn Sie in groß genug Stücke erweitern (etwa 64 MB, aber es hängt davon ab, wie schnell es wächst), dann die Kosten für die alte Karte für unwirksam zu erklären ist vernachlässigbar. Wie immer, Benchmark vor der Annahme eines Problems.

Verwandte Themen