所以我有一个我用mmap()分配的内存区域,类似于下面的代码:
void * ptr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
这里的关键是我使用MAP_SHARED标志。与this相关的问题不同,只需再次调用mmap()来获取MAP_PRIVATE和Copy-on-Write语义就足够了,我不能让内核为我分配不同范围的虚拟地址。另外,在我再次调用mmap()之前,我不想调用munmap()并冒险让内核将部分/全部地址范围提供给进程中的其他内容。
是否存在将mmap&#t;内存区域从MAP_SHARED切换到MAP_PRIVATE以获取写时复制语义而不取消映射块的现有机制?
答案 0 :(得分:1)
再次使用mmap()
致电MAP_PRIVATE | MAP_FIXED
即可。 MMAP(2)手册页说明使用MAP_FIXED
时:
如果无法使用指定的地址,则mmap()将失败。
因此,只需使用临时指针来存储mmap()
结果。如果mmap()
失败,则不会造成任何伤害。如果mmap()
成功,则表示您已成功将内存映射区域从MAP_SHARED
切换为MAP_PRIVATE
。 (见例)
#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);
}