Domanda

Sto cercando di trovare il modo di rimappare i file mappati in memoria su un Mac (quando voglio per ampliare lo spazio a disposizione).

I vedere i nostri amici nel mondo Linux hanno mremap ma riesco a trovare nessuna tale funzione nelle intestazioni sul mio Mac. /Developer/SDKs/MacOSX10.6.sdk/usr/include/sys/mman.h ha la seguente:

  • mmap
  • mprotect
  • msync
  • munlock
  • munmap
  • , ma non mremap

man mremap conferma le mie paure.

Al momento sto dover munmap e mmmap se voglio ridimensionare la dimensione del file mappato, che coinvolge invalidando tutte le pagine caricate. Ci deve essere un modo migliore. Sicuramente?

Sto cercando di scrivere il codice che funziona su Mac OS X e Linux. Potrei accontentarsi di una macro per utilizzare la funzione migliore in ogni caso se had per ma preferirei farlo correttamente.

È stato utile?

Soluzione

È possibile ftruncate il file di grandi dimensioni (la creazione di un foro) e mmap tutto. Se il file è persistente vi consiglio di riempire il buco con le chiamate di scrittura, piuttosto che scrivendo nella mappatura, altrimenti i blocchi del file possono ottenere inutilmente frammentato sul disco.

Altri suggerimenti

Se è necessario per ridurre la mappa, basta munmap la parte alla fine che si desidera rimuovere.

Se è necessario ingrandire la mappa, è possibile mmap l'offset con MAP_FIXED agli indirizzi appena sopra la vecchia mappa corretta, ma è necessario fare attenzione che non si mappa su qualcosa d'altro che è già lì. ..

Il testo sotto strikeout è un'idea terribile; MAP_FIXED è fondamentalmente sbagliato a meno che non sai già che cosa è presso l'indirizzo di destinazione e vuole sostituire atomicamente esso. Se si sta cercando di mappare opportunisticamente qualcosa di nuovo se l'intervallo di indirizzi è gratuita, è necessario utilizzare mmap con un indirizzo richiesto, ma senza MAP_FIXED e vedere se riesce e ti dà l'indirizzo richiesto; se ha successo, ma con un indirizzo diverso ti consigliamo di eliminare la mappatura della nuova mappatura che avete appena creato e supponiamo che l'allocazione presso l'indirizzo richiesto non è stato possibile.

Se si espande in grossi pezzi abbastanza (diciamo, 64 MB, ma dipende da quanto velocemente cresce) allora il costo di invalidare la vecchia mappa è trascurabile. Come sempre, punto di riferimento prima di assumere un problema.

Non ho esperienza con la mappatura della memoria, ma sembra che è possibile mappare temporaneamente lo stesso file due volte come un mezzo per ampliare la mappatura senza perdere nulla.

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 );
}

L'uscita è zxxxxxxxxxyyyyyy.....

suppongo, se si libra su questo, può essere possibile a corto di spazio di indirizzamento più velocemente che con mremap. Ma nulla è garantito in entrambi i casi e potrebbe essere d'altra parte altrettanto sicuri.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top