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

时间:2015-03-23 12:58:19

标签: c mmap

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

由于

修改 操作系统: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] = '\0';

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

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

2 个答案:

答案 0 :(得分:3)

映射大于内存总量的文件是可能的(并且非常正常),但您的应用必须能够解决它。如果您的系统/应用程序是32位,则您的地址范围有限。你的系统&amp;应用程序必须是64位才能解决大于几千兆字节大小的文件......

请注意:即使您的文件很小,您仍可能无法映射它。也许您通过简单地为其他目的分配内存(线程的堆栈空间,应用程序缓冲区/列表的内存等)来消耗地址空间。

答案 1 :(得分:2)

以下是The GNU C Library: Memory-mapped I/O

的摘录
  

由于mmapped页面可以在物理内存不足时存储回文件,因此可以mmap大于物理内存和交换空间的数量级。唯一的限制是地址空间。 32位机器上的理论限制是4GB - 然而,实际限制将会更小,因为某些区域将被保留用于其他目的。