2014-12-24 31 views
5

Ho eseguito il programma con privilegio di root ma continua a lamentarsi che mmap non può allocare memoria. Lo snippet di codice è qui sotto:Perché mmap non può allocare memoria?

#define PROTECTION (PROT_READ | PROT_WRITE) 
#define LENGTH (4*1024) 

#ifndef MAP_HUGETLB 
#define MAP_HUGETLB 0x40000 
#endif 

#define ADDR (void *) (0x0UL) 
#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB) 

int main (int argc, char *argv[]){ 
... 
    // allocate a buffer with the same size as the LLC using huge pages 
    buf = mmap(ADDR, LENGTH, PROTECTION, FLAGS, 0, 0); 
    if (buf == MAP_FAILED) { 
    perror("mmap"); 
    exit(1); 
    } 
...} 

Hardware: Ho 8G di RAM. Il processore è Ivybridge uscita

Uname:

Linux mymachine 3.13.0-43-generiC#72-Ubuntu SMP Mon Dec 8 19:35:06 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux 

EDIT 1: L'uscita del perror

mmap: Cannot allocate memory 

aggiunto anche una linea per stampare errno

printf("something is wrong: %d\n", errno); 

Ma l'output è:

something is wrong: 12 

EDIT 2: L'enorme informazioni relative TLB da/proc/meminfo

HugePages_Total:  0 
HugePages_Free:  0 
HugePages_Rsvd:  0 
HugePages_Surp:  0 
Hugepagesize:  2048 kB 
+1

hai controllato l'errore? [o] qual è l'output di 'perror()'? –

+0

Nessun problema con il mio OSX. –

+0

Sei sicuro del valore della tua costante 'MAP_HUGETLB'? –

risposta

0

Quando si utilizza MAP_HUGETLB, la chiamata mmap(2) può fallire (per esempio se il tuo sistema non ha enormi pagine configurate, o se qualche risorsa è esaurita), quindi quasi sempre dovresti chiamare mmap senza MAP_HUGETLB come fallimento. Inoltre, non è necessario definire MAP_HUGETLB. Se non è definito (dalle intestazioni di sistema interne a <sys/mman.h>, potrebbe essere diverso in base alle architetture o alle versioni del kernel), non utilizzarlo!

// allocate a buffer with the same size as the LLC using huge pages 
buf = mmap(NULL, LENGTH, PROTECTION, 
#ifdef MAP_HUGETLB 
      MAP_HUGETLB | 
#endif 
      MAP_PRIVATE | MAP_ANONYMOUS, 
      0, 0); 
#ifdef MAP_HUGETLB 
    if (buf == MAP_FAILED) { 
    // try again without huge pages: 
    buf = mmap(NULL, LENGTH, PROTECTION, 
       MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 
    }; 
#endif 
if (buf == MAP_FAILED) { 
    perror("mmap"); 
    exit(EXIT_FAILURE); 
} 

Documentation/vm/hugetlspage.txt menzione del kernel che enormi pagine sono -o possono essere- limitati (ad esempio, se si passa hugepages=N al kernel, oppure se si fanno le cose attraverso /proc/ o /sys/, o se questo non era configurato nel kernel , eccetera...). Quindi non sei sicuro di averli. E usare pagine enormi per una piccola mappatura di soli 4Kbytes è un errore (o forse un fallimento). Le pagine enormi valgono la pena solo quando si chiede molti megabyte (ad esempio un gigabyte o più) e si è sempre un'ottica di ottimizzazione (ad esempio, si vorrebbe che l'applicazione sia in grado di essere eseguita su un kernel senza di essi).

+0

Voglio chiedere a mmap di usare enorme tlb. Come dovrei risolvere questo errore? – drdot

+0

Perché 'mmap' con' MAP_HUGETLB' può fallire? per favore fornisci qualche link a riguardo, sia [mmap] (http://man7.org/linux/man-pages/man2/mmap.2.html) che [hugetlbpage] (https://www.kernel.org/doc /Documentation/vm/hugetlbpage.txt) non parlava di 'mmap' con' MAP_HUGETLB' può fallire – D3Hunter

+0

@jujj, e Basile Starynkevitch, ho cambiato la dimensione di mappatura in 4 * 1024 * 1024 e ho applicato il comando echo fornito da jujj. Funziona ora. Ma dal momento che entrambi avete fornito parte della soluzione, non so chi è la risposta da prendere. Ma penso che Basile abbia pubblicato prima il documento e la spiegazione del kernel. Nota: con il solo comando echo, avrò ancora errori di seg in seguito nel mio programma. – drdot