Ho lavorato con file sparsi di grandi dimensioni su openSUSE 11.2 x86_64. Quando provo a mmap() un file sparse da 1TB, fallisce con ENOMEM. Avrei pensato che lo spazio di indirizzamento a 64 bit sarebbe stato adeguato per mappare in un terabyte, ma non sembra. Sperimentando ulteriormente, un file da 1 GB funziona bene, ma un file da 2 GB (e qualcosa di più grande) fallisce. Immagino che ci possa essere un'ambientazione da modificare, ma una ricerca approfondita non rivela nulla.Perché mmap() non riesce con ENOMEM su un file sparse da 1TB?
Ecco un esempio di codice che mostra il problema: qualche indizio?
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
char * filename = argv[1];
int fd;
off_t size = 1UL << 40; // 30 == 1GB, 40 == 1TB
fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666);
ftruncate(fd, size);
printf("Created %ld byte sparse file\n", size);
char * buffer = (char *)mmap(NULL, (size_t)size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (buffer == MAP_FAILED) {
perror("mmap");
exit(1);
}
printf("Done mmap - returned 0x0%lx\n", (unsigned long)buffer);
strcpy(buffer, "cafebabe");
printf("Wrote to start\n");
strcpy(buffer + (size - 9), "deadbeef");
printf("Wrote to end\n");
if (munmap(buffer, (size_t)size) < 0) {
perror("munmap");
exit(1);
}
close(fd);
return 0;
}
Come punto di interesse, il programma funziona per me fino a una dimensione di 256 GB ('1 << 38'), con qualcosa di più elevato che restituisce' EINVAL'. Questo è su RHEL4 (kernel 2.6.9-42.0.3.ELsmp). – caf
Cosa dice ulimit -a? – bmargulies
Grazie, bmargulies: era così. ulimit -a ha riferito la memoria virtuale come 1804800 kbyte (poco più di 1,7 GB). ulimit -v 1610612736 (1.5TB) mi consente di mmap il mio file sparse da 1TB. Risponderò alla mia domanda in modo che possa "chiuderla" ... – metadaddy