我的程序将数据指针传递给第三方插件,目的是数据应该是只读的,所以最好防止插件写入数据对象。理想情况下,如果插件尝试写入,则会出现段错误。我听说有一些方法可以双重映射一个内存区域,这样第二个虚拟地址范围就指向相同的物理内存页面。第二个映射没有写权限,导出的指针将使用此地址范围而不是原始(可写)地址范围。我宁愿不改变原来的内存分配,无论他们碰巧使用 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;
}
编译:gcc test.c -std=c99 -lrt
出于某种原因,我收到一条警告,提示未声明 ftruncate。不知道为什么。该代码虽然运行良好。示例输出:
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
我已将内存释放留给读者作为练习:-)
关于C/Linux : dual-map memory with different permissions,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25400693/