将mmap的内存区域从MAP_SHARED更改为MAP_PRIVATE [英] Change an mmap'd memory region from MAP_SHARED to MAP_PRIVATE

查看:1456
本文介绍了将mmap的内存区域从MAP_SHARED更改为MAP_PRIVATE的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有一个用mmap()分配的内存区域,类似于下面的代码:

So I have a region of memory that I have allocated with mmap() similar to the code below:

void * ptr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

这里的关键是我正在使用MAP_SHARED标志.与相关问题足够了为了再次简单地调用mmap()以获得MAP_PRIVATE和写时复制语义,我无法让内核为我分配不同范围的虚拟地址.此外,在再次调用mmap()之前,我不想调用munmap()并冒着内核将部分/全部地址范围提供给进程中其他对象的风险.

The key here is that I'm using the MAP_SHARED flag. Unlike this related question where it was sufficient to simply call mmap() again to get MAP_PRIVATE and Copy-on-Write semantics, I can't have the kernel allocate me a different range of virtual addresses. In addition, I do not want to invoke munmap() and risk the kernel giving part/all of that address range to something else within the process before I can call mmap() again.

是否存在一种将mmap的内存区域从MAP_SHARED切换到MAP_PRIVATE的机制,以在不取消映射的情况下获得写时复制语义?

Is there an existing mechanism to switch a region of mmap'd memory from MAP_SHARED to MAP_PRIVATE to get copy-on-write semantics without unmapping the block?

推荐答案

使用MAP_PRIVATE | MAP_FIXED再次调用mmap()将起作用. MMAP(2)手册页指出使用MAP_FIXED:

Calling mmap() again with MAP_PRIVATE | MAP_FIXED will work. The MMAP(2) man page states that when using MAP_FIXED:

如果无法使用指定的地址,则mmap()将失败.

If the specified address cannot be used, mmap() will fail.

因此,只需使用一个临时指针来存储mmap()结果.如果mmap()失败,则无害.如果mmap()成功,则您已成功将内存映射区域从MAP_SHARED切换到MAP_PRIVATE. (请参见示例)

So, just use a temporary pointer to store the mmap() result. If mmap() fails, no harm done. If mmap() succeeds you have successfully switched a memory mapped region from MAP_SHARED to MAP_PRIVATE. (see example)

#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
    int fd;
    void *shared_0, *shared_1;
    void *private_0;
    struct stat st;

    if((fd = open("filename", O_RDWR, S_IRUSR | S_IWUSR)) < 0) {
        fprintf(stderr, "Failed to open(): %s\n", strerror(errno));
    }
    else if(fstat(fd, &st) < 0) {
        fprintf(stderr, "Failed fstat(): %s\n", strerror(errno));
    }
    else if((shared_0 = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE,
            MAP_SHARED, fd, 0)) == MAP_FAILED) {
        fprintf(stderr, "Failed to mmap(): %s\n", strerror(errno));
    }
    else if((shared_1 = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE,
            MAP_SHARED, fd, 0)) == MAP_FAILED) {
        fprintf(stderr, "Failed to mmap(): %s\n", strerror(errno));
    }
    else if((private_0 = mmap(shared_0, st.st_size, PROT_READ | PROT_WRITE,
            MAP_FIXED | MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
        fprintf(stderr, "Failed to mmap(): %s\n", strerror(errno));
    }
    else if(shared_0 != private_0) {
        fprintf(stderr, "Error: mmap() didn't map to the same region");
    }
    else {
        printf("shared_0: %p == private_0: %p\n", shared_0, private_0);
        printf("shared_1: %p\n", shared_1);

        printf("Shared mapping before write: %d\n", (*(char *)shared_1));
        printf("Private mapping before write: %d\n", (*(char *)private_0));

        /* write to the private COW mapping and sync changes */
        (*(char*)private_0) = 42;
        if(msync(private_0, 1, MS_SYNC | MS_INVALIDATE) < 0) {
            fprintf(stderr, "Failed msync(): %s\n", strerror(errno));
            return(1);
        }

        printf("Shared mapping after write: %d\n", (*(char *)shared_1));
        printf("Private mapping after write: %d\n", (*(char *)private_0));
    }

    return(0);
}

这篇关于将mmap的内存区域从MAP_SHARED更改为MAP_PRIVATE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆