Каков максимальный размер сопоставления файлов на 64-битной машине? - PullRequest
2 голосов
/ 29 января 2010

Я новичок в 64-битной архитектуре. Не могли бы вы сказать мне, какой размер файла MAX поддерживается сопоставлением файлов на 64-битной машине Linux. Я хочу открыть более 20 ГБ файлов путем сопоставления файлов, это доступно?

Я пишу пример кода. Но это вызывает Ошибка шины , когда я получаю значение указателя в смещении GBSIZE:

unsigned char* pCur = pBegin + GBSIZE;
//pBegin is the pointer returned by mmap
printf("%c",*pCur); 

Кстати, printf("%c",*pBegin ); отлично работает. и размеры моего адреса: физические 38 бит, виртуальные 48 бит

Вот полный код:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

//#define FILEPATH "smallfile"
#define FILEPATH "bigfile"
#define GBSIZE (1024L*1024L*1024L)
#define TBSIZE (1024L*GBSIZE)
#define NUMSIZE  (20L * GBSIZE)
//#define NUMSIZE  (10)
#define FILESIZE (NUMINTS * sizeof(int))

int main(int argc, char *argv[])
{
    int i;
    int fd;
    unsigned char *pBegin;

    fd = open(FILEPATH, O_RDONLY);
        if (fd == -1) {
        perror("Error opening file for reading");
        exit(EXIT_FAILURE);
    }

    pBegin = mmap(0, NUMSIZE, PROT_READ, MAP_SHARED, fd, 0);
    if (pBegin == MAP_FAILED) {
        close(fd);
        perror("Error mmapping the file");
        exit(EXIT_FAILURE);
    }

    /** ERROR happens here!!! **/
    unsigned char* pCur = pBegin + GBSIZE;
    printf("%c",*pCur);

    if (munmap(pBegin, NUMSIZE) == -1) {
        perror("Error un-mmapping the file");
    }
    close(fd);
    return 0;
}

Ответы [ 5 ]

10 голосов
/ 29 января 2010

Хотя указатели имеют ширину 64 бита, большинство процессоров фактически не поддерживают виртуальные адреса, использующие полные 64 бита. Чтобы узнать, какой размер виртуальных адресов поддерживает ваш процессор, посмотрите в /proc/cpuinfo (обычно 48 бит).

grep "address sizes" /proc/cpuinfo

Кроме того, половина виртуального адресного пространства используется ядром и недоступна для пользовательского пространства - в текущей реализации Linux осталось 47 бит.

Однако, даже принимая это во внимание, у вас все равно будет достаточно места для файла объемом 20 ГБ. 47 бит в теории означает виртуальное адресное пространство 128 ТБ.

5 голосов
/ 29 января 2010

Со страницы руководства mmap(2):

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

length - это size_t, длина которого на 64-разрядных компьютерах составляет 64 бита.Следовательно, теоретически вы можете отобразить файл размером 20 ГБ.

1 голос
/ 26 декабря 2014

(Этот ответ был первоначально отредактирован в вопросе OP)

Вы запросили карту размером 20 ГБ для файла размером всего 50 МБ.

Как описано , справочная страница mmap , mmap успешна, когда вы запрашиваете слишком большую длину, однако она даст SIGBUS или SIGSEGV, когда вы на самом деле пытаетесь читать после конца основной файл.

1 голос
/ 29 января 2010

64-битные адреса позволяют на много порядков больше 20 ГБ.

0 голосов
/ 16 июня 2017

Согласитесь с MarkR, вы разыменовываете неверный адрес.

// A bug in these lines.
unsigned char* pCur = pBegin + GBSIZE;      
printf("%c",*pCur);  

unsigned char* pEnd = pBegin + NUMSIZE;  
unsigned char* pLast = pEnd - 1;
unsigned char* pCur = pLast;

Я изменил ваш код для использования флагов HUGE TLB следующим образом.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

#define MAP_HUGETLB     0x40000         /*  create a huge page mapping */
#define MAP_HUGE_SHIFT  26
#define MAP_HUGE_1GB    (30 << MAP_HUGE_SHIFT)

#define KSIZE 1024L
#define MSIZE (1024L*1024L)
#define GSIZE (1024L*1024L*1024L)
#define TSIZE (1024L*GSIZE)

#define INIT_MEM 0
// Fail on my MacBook Pro (Retina, 13-inch, Early 2015)
// Darwin Kernel Version 16.5.0:x86_64
// #define NUMSIZE  (16L * TSIZE)

// mmap ok; init: got killed; signal 9
// #define NUMSIZE  (8L * TSIZE)

// Got killed signal 9
// #define NUMSIZE  (1L * TSIZE)

// OK
// #define NUMSIZE  (200L * GSIZE)

// OK
#define NUMSIZE  (20L * GSIZE)
typedef unsigned long long ETYPE;

#define MEMSIZE (NUMSIZE*sizeof(ETYPE))
#define PGSIZE (16*KSIZE)

void init(ETYPE* ptr) {
        *ptr = (ETYPE)ptr;
}

int verify(ETYPE* ptr) {
        if (*ptr != (ETYPE)ptr) {
                fprintf(stderr, "ERROR: 0x%016llx != %p.\n", *ptr, ptr);
                return -1;
        }
        else {
                fprintf(stdout, "OK: 0x%016llx = %p.\n", *ptr, ptr);
        }
        return 0;
}
int main(int argc, char *argv[])
{
    int i;
    int fd;
    ETYPE *pBegin;

    int flags = MAP_SHARED | MAP_ANONYMOUS | MAP_HUGETLB | MAP_HUGE_1GB;
    printf("mmap memory size:%lu GB\n", MEMSIZE/GSIZE);
    pBegin = (ETYPE*) mmap(0, MEMSIZE, PROT_READ | PROT_WRITE, flags, -1, 0);
    if (pBegin == MAP_FAILED) {
        perror("Error mmapping the file");
        exit(EXIT_FAILURE);
    }

    ETYPE* pEnd = pBegin + NUMSIZE;
    ETYPE* pCur = pBegin;

#if INIT_MEM
    while (pCur < pEnd) {
            init(pCur);
            // ++pCur;  //slow if init all addresses.
            pCur += (PGSIZE/sizeof(ETYPE)); 
    }
#endif

    init(&pBegin[0]);
    init(&pBegin[NUMSIZE-1]);

    verify(&pBegin[0]);
    verify(&pBegin[NUMSIZE-1]);

    if (munmap(pBegin, MEMSIZE) == -1) {
        perror("Error un-mmapping the file");
    }
    return 0;
}
...