2016-02-22 11 views
7

Ich habe ein C-Programm, das den Seitenfehler Servicezeit in C. Für dieses Programm Ich habe 2 große Dateien (jeweils weniger als 3 GB - fast die Größe des RAM) berechnetmmap: zuteilen Speicher kann nicht

#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <sys/mman.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include "rdstc.h" 
#include "config.h" 

#define KB 1024 
#define MB 1024 * KB 
#define GB 1024 * MB 
#define SIZE_OF_MEMORY 1 * GB // Main memory size 

#define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0) 

int main(int argc, char *argv[]){ 

    int fd1, fd2; 
    char *addr1, *addr2, c; 
    int i, j; 
    long long unsigned int s_t, e_t, t=0; 

    if (argc != 3){ 
     printf("usage: a.out <file1> <file2> \n"); 
     exit(EXIT_FAILURE); 
    } 

    if ((fd1 = open(argv[1], O_RDONLY)) == -1){ 
     handle_error("open"); 
    } 

    if ((fd2 = open(argv[2], O_RDONLY)) == -1){ 
     handle_error("open"); 
    } 

    posix_fadvise(fd1, 0, 0, POSIX_FADV_RANDOM); 
    posix_fadvise(fd2, 0, 0, POSIX_FADV_RANDOM); 

    addr1 = (char *) mmap(0, SIZE_OF_MEMORY, PROT_READ, MAP_PRIVATE | MAP_POPULATE, fd1, 0); 
    if (addr1 == MAP_FAILED){ 
     handle_error("mmap"); 
    } 
    addr2 = (char *) mmap(0, SIZE_OF_MEMORY, PROT_READ, MAP_PRIVATE | MAP_POPULATE, fd2, 0); 
    if (addr2 == MAP_FAILED){ 
     handle_error("mmap"); 
    } 

    madvise(addr1, 0, MADV_RANDOM); 
    madvise(addr2, 0, MADV_RANDOM); 

    j = 32;  // default read ahead size if 256 blocks (assuming each block is of 512 bytes) 
    for(i = 0; i < ITERATIONS; i++){ 
     s_t = rdtsc(); 
      c = addr1[i + j*4*KB];  // read at multiple of page size, so every read causes a page fault 
      j *= 2; 
     e_t = rdtsc(); 
     t += (e_t - s_t); 
    } 
    printf("Time required to service a page faut is %f \n", (t/ITERATIONS)/CPU_FREQ); 

    munmap(addr1, SIZE_OF_MEMORY); 
    munmap(addr2, SIZE_OF_MEMORY); 

    return 0; 
} 

erhalte ich die folgende Compiler-Warnungen:

[email protected]:~/projects/mem$ gcc mem1_4.c -lm 
mem1_4.c: In function ‘main’: 
mem1_4.c:11:17: warning: integer overflow in expression [-Woverflow] 
#define MB 1024 * KB 
       ^
mem1_4.c:12:19: note: in expansion of macro ‘MB’ 
#define GB 1024 * MB 
       ^
mem1_4.c:13:28: note: in expansion of macro ‘GB’ 
#define SIZE_OF_MEMORY 2 * GB // Main memory size 
          ^
mem1_4.c:40:30: note: in expansion of macro ‘SIZE_OF_MEMORY’ 
    addr1 = (char *) mmap(0, SIZE_OF_MEMORY, PROT_READ, MAP_PRIVATE | MAP_POPULATE, fd1, 0); 
          ^
mem1_4.c:11:17: warning: integer overflow in expression [-Woverflow] 
#define MB 1024 * KB 
       ^
mem1_4.c:12:19: note: in expansion of macro ‘MB’ 
#define GB 1024 * MB 
       ^
mem1_4.c:13:28: note: in expansion of macro ‘GB’ 
#define SIZE_OF_MEMORY 2 * GB // Main memory size 
          ^
mem1_4.c:44:30: note: in expansion of macro ‘SIZE_OF_MEMORY’ 
    addr2 = (char *) mmap(0, SIZE_OF_MEMORY, PROT_READ, MAP_PRIVATE | MAP_POPULATE, fd2, 0); 
          ^
mem1_4.c:11:17: warning: integer overflow in expression [-Woverflow] 
#define MB 1024 * KB 
       ^
mem1_4.c:12:19: note: in expansion of macro ‘MB’ 
#define GB 1024 * MB 
       ^
mem1_4.c:13:28: note: in expansion of macro ‘GB’ 
#define SIZE_OF_MEMORY 2 * GB // Main memory size 
          ^
mem1_4.c:62:19: note: in expansion of macro ‘SIZE_OF_MEMORY’ 
    munmap(addr1, SIZE_OF_MEMORY); 
       ^
mem1_4.c:11:17: warning: integer overflow in expression [-Woverflow] 
#define MB 1024 * KB 
       ^
mem1_4.c:12:19: note: in expansion of macro ‘MB’ 
#define GB 1024 * MB 
       ^
mem1_4.c:13:28: note: in expansion of macro ‘GB’ 
#define SIZE_OF_MEMORY 2 * GB // Main memory size 
          ^
mem1_4.c:63:19: note: in expansion of macro ‘SIZE_OF_MEMORY’ 
    munmap(addr2, SIZE_OF_MEMORY); 
       ^

Wenn ich es mit dem Befehl ausführen erhalte ich die Fehler

./a.out file1.txt file2.txt 
mmap: Cannot allocate memory 

Was macht der Code? Wir bilden sowohl die Dateien Flaggen

MAP_PRIVATE mit (so dass kein anderer Prozess sollte auf diese Datei zugreifen) und MAP_POPULATE (so dass

wenn wir nennen mmap() vollständige Datei im Speicher abgebildet wird) zusammen mit PROT_READ Schutz Flagge.

Zuerst ordnen wir file1 zu, und da wir MAP_POPULATE verwenden, wird der komplette RAM mit Daten gefüllt, die dieser Datei entsprechen. Danach ordnen wir file2 mit den gleichen Flags zu und so haben wir file2 komplett im RAM gemappt. Der Zugriff auf Daten von Datei1 führt daher zu Seitenfehlern, da Datei2 den gesamten verfügbaren RAM belegt. Wir rufen auch madvise() syscall mit gesetztem MADV_RANDOM-Flag auf, um dem Kernel zu empfehlen, das Lesen von Seiten im Voraus für beide Dateien nicht zu lesen. Nun, nachdem diese Ersteinrichtung vorgenommen wurde, während Datei2 den gesamten verfügbaren RAM belegt, greifen wir wahlfrei auf Daten zu, die Datei1 entsprechen (um jeglichen Effekt der Read-Ahead-Leseoptimierung durch den Kernel zu vermeiden und außerdem das Lesen aus dem L3-Cache zu vermeiden) Daten entsprechend Datei2, verursacht jeder Zugriff auf Daten, die der Datei entsprechen, einen Seitenfehler. Wir führen 10 zufällige Messungen über die gemappte Region in der Schleife durch und messen die mittlere Zeit, die für diese Operation benötigt wird.

+0

Die Compiler-Warnungen sollten Sie einen Hinweis geben - 2 * 1024 * 1024 * 1024 auf eine negative Zahl überschwemmt. – immibis

Antwort

6

werfen Sie einen Blick auf die Compiler-Warnung erhalten Sie. Sie haben hier einen ganzzahligen Überlauf: #define SIZE_OF_MEMORY 2 * GB. Das entspricht 2^31 == 0b1000 ... 0, die für int int int gleich INT_MIN ist. Deshalb schlägt mmap fehl.

Sie sollten unsigned literals in Ihrem definiert verwenden:

#define KB (1024u) 
#define MB (1024u * KB) 
#define GB (1024u * MB) 
#define SIZE_OF_MEMORY (2u * GB) 
+2

... und fügen Sie bitte Klammern hinzu! – wildplasser

Verwandte Themen