mmap: не удается выделить память

у меня есть программа C, которая вычисляет время обслуживания ошибок страницы в C. Для этой программы у меня есть 2 больших файла (менее 3 ГБ каждый-почти размер ОЗУ)

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

Я получаю следующее предупреждение компилятора:

lmelvix@Melvix:~/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);
                ^

когда я запускаю его с помощью команды, я получаю ошибку

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

что делает этот код Мы сопоставляем оба файла с помощью flags

MAP_PRIVATE (так что никакой другой процесс не должен получить доступ к этому файлу) и MAP_POPULATE (так это

когда мы вызываем mmap (), полный файл отображается в памяти) вместе с флагом защиты PROT_READ.

Сначала мы сопоставляем file1, и поскольку мы используем MAP_POPULATE, полная ОЗУ заполняется данными, соответствующими этому файлу. После этого мы сопоставляем file2, используя те же флаги, и, таким образом, теперь у нас есть file2 полностью отображен в ОЗУ. Таким образом, доступ к данным file1 вызовет ошибки страницы, так как file2 занимает всю доступную ОЗУ. Мы также вызываем madvise () syscall с установленным флагом MADV_RANDOM, чтобы посоветуйте ядру не делать чтение вперед чтения страниц, для обоих файлов. Итак, теперь, когда эта начальная настройка выполняется с file2, занимающим всю доступную ОЗУ, мы получаем доступ к данным, соответствующим file1 случайным образом (чтобы избежать любого эффекта оптимизации чтения вперед, выполняемой ядром, а также избежать чтения из кэша L3), так как ОЗУ заполняется данными, соответствующими file2, каждый доступ к данным, соответствующим файлу, вызовет ошибку страницы. Мы выполняем 10 случайных показаний по отображаемой области в цикле и измерить среднее время, необходимое для этой операции.

1 ответов


взгляните на предупреждение компилятора, которое вы получаете. У вас есть целое переполнение здесь:#define SIZE_OF_MEMORY 2 * GB. Это равно 2^31 ==0b1000 ... 0 что для подписанного int равно INT_MIN. Вот почему mmap не удается.

вы должны использовать неподписанные литералы в своем определяет:

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