C/Linux:具有不同权限的双映射内存

C/Linux:具有不同权限的双映射内存,c,linux,mmap,C,Linux,Mmap,我的程序将数据指针传递给第三方插件,目的是数据应该是只读的,因此最好防止插件写入数据对象。理想情况下,如果插件尝试写入,将出现segfault。我听说有一种方法可以双重映射内存区域,这样第二个虚拟地址范围就指向相同的物理内存页。第二个映射没有写权限,导出的指针将使用此地址范围而不是原始(可写)地址范围。我宁愿不改变原始的内存分配,不管它们是使用malloc还是mmap或者其他什么。有人能解释一下怎么做吗?可以得到双重映射,但需要做一些工作 我知道如何创建这种双重映射的唯一方法是使用mmap函数调

我的程序将数据指针传递给第三方插件,目的是数据应该是只读的,因此最好防止插件写入数据对象。理想情况下,如果插件尝试写入,将出现segfault。我听说有一种方法可以双重映射内存区域,这样第二个虚拟地址范围就指向相同的物理内存页。第二个映射没有写权限,导出的指针将使用此地址范围而不是原始(可写)地址范围。我宁愿不改变原始的内存分配,不管它们是使用malloc还是mmap或者其他什么。有人能解释一下怎么做吗?

可以得到双重映射,但需要做一些工作

我知道如何创建这种双重映射的唯一方法是使用
mmap
函数调用。对于mmap,您需要某种文件描述符。幸运的是,Linux允许您获取共享内存对象,因此不需要存储介质上的真实文件

下面是一个完整的示例,演示如何创建共享内存对象,从中创建读/写和只读指针,然后执行一些基本测试:

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

int main()  
{
        // Lets do this demonstration with one megabyte of memory:
        const int len = 1024*1024;

        // create shared memory object:
        int fd = shm_open("/myregion", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
        printf ("file descriptor is %d\n", fd);

        // set the size of the shared memory object:
        if (ftruncate(fd, len) == -1)
        {
            printf ("setting size failed\n");
            return 0;
        }

        // Now get two pointers. One with read-write and one with read-only.
        // These two pointers point to the same physical memory but will
        // have different virtual addresses:

        char * rw_data = mmap(0, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd,0);
        char * ro_data = mmap(0, len, PROT_READ           , MAP_SHARED, fd,0);

        printf ("rw_data is mapped to address %p\n", rw_data);
        printf ("ro_data is mapped to address %p\n", ro_data);

        // ===================
        // Simple test-bench:
        // ===================

        // try writing:
        strcpy (rw_data, "hello world!");

        if (strcmp (rw_data, "hello world!") == 0)
        {
            printf ("writing to rw_data test passed\n");
        } else {
            printf ("writing to rw_data test failed\n");
        }

        // try reading from ro_data
        if (strcmp (ro_data, "hello world!") == 0)
        {
            printf ("reading from ro_data test passed\n");
        } else {
            printf ("reading from ro_data test failed\n");
        }

        printf ("now trying to write to ro_data. This should cause a segmentation fault\n");

        // trigger the segfault
        ro_data[0] = 1;

        // if the process is still alive something didn't worked.
        printf ("writing to ro_data test failed\n");
        return 0;
}

我把内存释放留给读者作为一个练习:-)

可能有点相关(尽管它没有解决这个问题的所有方面)。谢谢你的全面回答。但是如果内存最初是用malloc分配的--有没有办法将文件描述符与之关联,或者是通过mmap无法访问它?在我无法更改原始分配的情况下,它可以很好地复制和重新映射分配的内存。@ByronHawkins据我所知,您无法从使用不同方法分配的内存中获得具有不同访问权限的第二个指针。
file descriptor is 3
rw_data is mapped to address 0x7f1778d60000
ro_data is mapped to address 0x7f1778385000
writing to rw_data test passed
reading from ro_data test passed
now trying to write to ro_data. This should cause a segmentation fault
Segmentation fault