什么是64位机器中的最大文件映射大小

时间:2010-01-29 02:13:28

标签: linux 64-bit filemap

我是64位架构的新手。你能告诉我64位linux机器中文件映射支持的MAX文件大小吗?我想通过文件映射打开超过20GB的文件,是否可用?

我写了一个示例代码。但是当我在GBSIZE偏移量中得到指针的值时,它会导致总线错误

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

BTW,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 个答案:

答案 0 :(得分:9)

虽然指针是64位宽,但大多数处理器实际上并不使用完整的64位来支持虚拟地址。要查看处理器支持的虚拟地址大小,请查看/proc/cpuinfo(通常为48位)。

grep "address sizes" /proc/cpuinfo

此外,一半的虚拟地址空间由内核使用,不可供用户空间使用 - 在当前的Linux实现中留下47位。

然而,即使考虑到这一点,你仍然会有足够的空间来容纳20GB的文件。理论上47位意味着128TB的虚拟地址空间。

答案 1 :(得分:5)

来自mmap(2)手册页:

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

lengthsize_t,在64位计算机上长度为64位。因此,是的,理论上你可以映射一个20GB的文件。

答案 2 :(得分:1)

64位地址允许超过20 GB的许多数量级。

答案 3 :(得分:1)

(这个答案最初是由OP编写的问题)

您已经请求将20GB的地图放到一个只有50MB大小的文件上。

正如the mmap man page所述,mmap在请求长度过大时会成功,但是当您实际尝试阅读超出结束时,它会给SIGBUSSIGSEGV底层文件。

答案 4 :(得分:0)

同意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;

我修改了你的代码以使用巨大的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;
}