Почему mmap () не работает с ENOMEM для файла размером 1 ТБ - PullRequest
10 голосов
/ 26 мая 2010

Я работал с большими разреженными файлами в openSUSE 11.2 x86_64. Когда я пытаюсь выполнить mmap () разреженный файл размером 1 ТБ, он завершается неудачно с ENOMEM. Я бы подумал, что 64-битное адресное пространство будет достаточно для отображения в терабайтах, но, похоже, нет. Экспериментируя далее, файл 1 ГБ работает нормально, но файл 2 ГБ (и все, что больше) не удается. Я предполагаю, что где-то может быть настройка, но расширенный поиск ничего не даст.

Вот пример кода, который показывает проблему - какие-либо подсказки?

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

Ответы [ 3 ]

12 голосов
/ 27 мая 2010

Проблема заключалась в том, что ограничение виртуальной памяти для каждого процесса было установлено только в 1,7 ГБ.ulimit -v 1610612736 установить его на 1,5 ТБ, и мой вызов mmap () завершился успешно.Спасибо, bmargulies , за подсказку попробовать ulimit -a!

2 голосов
/ 26 мая 2010

Существует ли какая-то квота на пользователя, ограничивающая объем памяти, доступной для пользовательского процесса?

1 голос
/ 26 мая 2010

Я предполагаю, что ядру трудно выделить память, необходимую для соответствия этому отображению памяти. Я не знаю, как сохраненные страницы сохраняются в ядре Linux (и я предполагаю, что большая часть файла будет находиться в состоянии замены) большую часть времени, но может потребоваться запись для каждой страницы памяти, которую файл занимает в таблице. Поскольку этот файл может быть отображен более чем одним процессом, ядро ​​должно следить за отображением с точки зрения процесса, которое сопоставляется с другой точкой зрения, которая сопоставляется с вторичным хранилищем (и включает поля для устройства и местоположения). ).

Это вписывается в ваше адресуемое пространство, но может не помещаться (хотя бы непрерывно) в физическую память.

Если кто-нибудь знает больше о том, как это делает Linux, мне было бы интересно узнать об этом.

...