2013-08-24 9 views
18

Sto ricevendo -EINVAL per qualche motivo, e non mi è chiaro il perché. Ecco dove apro e tentare di mmap file:Argomento non valido per mmap di lettura-scrittura?

if ((fd = open(argv[1], O_RDWR)) < 0) 
{ 
    fprintf(stderr, "Failed to open %s: %s\n", argv[1], strerror(errno)); 
    return 1; 
} 

struct stat statbuf; 
if (fstat(fd, &statbuf)) 
{ 
    fprintf(stderr, "stat filed: %s\n", strerror(errno)); 
    return 1; 
} 

char* fbase = mmap(NULL, statbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 
if (fbase == MAP_FAILED) 
{ 
    fprintf(stderr, "mmap failed: %s\n", strerror(errno)); 
    return 1; 
} 

EDIT: Vorrei aggiungere, si verifica l'errore nel mmap.

+0

Cosa intendi? Questo è un frammento di qualcosa che sto scrivendo. – Alex

+0

La domanda è "dove" in quale riga del frammento di codice si verifica l'EINVAL. – alk

+0

Siamo spiacenti, ho dimenticato di specificare. L'errore è in mmap. – Alex

risposta

49

Risulta cambiare il MAP_SHARED- MAP_PRIVATE permette questo per avere successo.

Questa ragione per cui questo stava venendo a mancare è sottile: Il mio codice è in esecuzione all'interno di una macchina virtuale VirtualBox, e il file che stava tentando di mmap era in una directory condivisa sulla mia macchina host. Apparentemente il filesystem virtuale VirtualBox non implementa mmap con l'opzione MAP_SHARED oltre il limite dell'hypervisor.

Se leggerai i commenti utili di jxh sia sulla mia domanda sia sulla sua risposta, si scopre che questo codice stava funzionando per lui perché probabilmente stava tentando di inserire un file system host nella memoria dell'host nel file mmap.

La mia osservazione è che il passaggio da MAP_SHARED a MAP_PRIVATE è coerente con questo: poiché la memoria mappata privatamente è invisibile ad altri processi, il driver del filesystem virtuale probabilmente non avrà obiezioni a mappare la memoria.

La soluzione era spostare il file che volevo mappare nel disco rigido del guest ed eseguire la manipolazione da lì.

+2

Questa è una buona scoperta, +1. – jxh

+2

Questo l'ha risolto per me! – arnoapp

+2

Ecco perché amo lo stackoverflow. – Claudiu

13

Il tuo statbuf.st_size è 0. mmap() non riuscirà se il parametro è 0.

Ci sono 3 motivi elencati per EINVAL errore mmap():

void *mmap(void *addr, size_t length, int prot, int flags, 
      int fd, off_t offset); 

...

  • Non ci piace addr, length, o offset (ad esempio, sono troppo grandi o non allineato sul confine di una pagina).
  • (a partire da Linux 2.6.12) length era di 0
  • flags conteneva né MAP_PRIVATE o MAP_SHARED, o contenuti entrambi questi valori.
+0

Mi sento un deficiente, ma: era zero, ho sostituito il file vuoto e il problema persiste. – Alex

+0

Mentre la lunghezza era zero in precedenza, ho assicurato che il file non era vuoto e il problema è ancora presente. Questa domanda è un disastro, ne aprirò una nuova con maggiori dettagli. – Alex

+0

Ho compilato e eseguito correttamente il codice sul mio sistema Linux. – jxh