C/C++ - 使用 mmap 的内存映射文件

C/C++ - Memory map file using mmap

我是内存映射文件的新手,有点困惑。是否可以映射大于内存总量的文件,因为据我所知,内存映射使用需求分页,并且只会在内存中保留当前相关的页面。这是正确的还是我的应用程序在使用比实际内存多 space 时会崩溃。

谢谢

编辑 OS:Ubuntu 14.04 LTS x86_64 App-Bitness:64bit(我猜:指针是8字节)

我正在尝试从映射文件分配内存,以便将树存储在映射文件中。

#define MEMORY_SIZE 300000000

unsigned char *mem_buffer;
void *start_ptr;

void *my_malloc(int size) {
    unsigned char *ptr = mem_buffer;
    mem_buffer += size;

    return ptr;
}

void *my_calloc(int size, int object_size) {
    unsigned char *ptr = mem_buffer;
    mem_buffer += (size * object_size);

    return ptr;
}

void init(const char *file_path) {
    int fd = open(file_path, O_RDWR, S_IREAD | S_IWRITE);

    if (fd < 0) {
        perror("Could not open file for memory mapping");
        exit(1);
    }

    start_ptr = mmap(NULL, MEMORY_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
    mem_buffer = (unsigned char *) start_ptr;

    if (mem_buffer == MAP_FAILED) {
        perror("Could not memory map file");
        exit(1);
    }

    printf("Successfully mapped file.\n");
}

void unmap() {
    if (munmap(start_ptr, MEMORY_SIZE) < 0) {
        perror("Could not unmap file");
        exit(1);
    }

    printf("Successfully unmapped file.\n");
}

主要方法:

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

    init(argv[1]);

    unsigned char *arr = (unsigned char *) my_malloc(6);
    arr[0] = 'H';
    arr[1] = 'E';
    arr[2] = 'L';
    arr[3] = 'L';
    arr[4] = 'O';
    arr[5] = '[=12=]';

    unsigned char *arr2 = (unsigned char *) my_malloc(5);
    arr2[0] = 'M';
    arr2[1] = 'I';
    arr2[2] = 'A';
    arr2[3] = 'U';
    arr2[4] = '[=12=]';

    printf("Memory mapped string1: %s\n", arr);
    printf("Memory mapped string2: %s\n", arr2);

    struct my_btree_node *root = NULL;

    insert(&root, arr, 10);
    insert(&root, arr2, 20);

    print_tree(root, 0, false);

//  cin.ignore();

    unmap();

    return EXIT_SUCCESS;
}

映射大于内存总量的文件是可能的(而且非常正常),但您的应用必须能够解决它。如果您的 system/app 是 32 位的,那么您的地址范围是有限的。您的系统和应用程序必须是 64 位的才能处理大于几 GB 大小的文件...

请注意:即使您的文件很小,您仍然可能无法映射它。也许您通过简单地为其他目的分配内存(堆栈 space 用于线程,内存用于应用程序 buffers/lists 等)

消耗了您的地址 space

这里摘录自The GNU C Library: Memory-mapped I/O

Since mmapped pages can be stored back to their file when physical memory is low, it is possible to mmap files orders of magnitude larger than both the physical memory and swap space. The only limit is address space. The theoretical limit is 4GB on a 32-bit machine - however, the actual limit will be smaller since some areas will be reserved for other purposes.