C 使用mremap重新分配内存
我试图使用malloc分配两个不同的4096字节,并用不同的值初始化这些分配。之后,我希望其中一个指针指向另一个分配,“不”更改p1的值,“不”复制数据。我想将第二个分配“重新映射”到第一个分配,这将基本上更改流程页表中的虚拟地址,即不涉及复制。当我运行这段代码时,我发现mremap失败了。你知道如何做到这一点吗C 使用mremap重新分配内存,c,linux,memory-management,C,Linux,Memory Management,我试图使用malloc分配两个不同的4096字节,并用不同的值初始化这些分配。之后,我希望其中一个指针指向另一个分配,“不”更改p1的值,“不”复制数据。我想将第二个分配“重新映射”到第一个分配,这将基本上更改流程页表中的虚拟地址,即不涉及复制。当我运行这段代码时,我发现mremap失败了。你知道如何做到这一点吗 int main(){ char *p1 = (char *)malloc(4096); memset(p1, 'a', 4096); char *p2 = (
int main(){
char *p1 = (char *)malloc(4096);
memset(p1, 'a', 4096);
char *p2 = (char *)malloc(4096);
memset(p2, 'b', 4096);
printf("p1 is %c at address %p\n", p1[0], p1);
printf("p2 is %c at address &p\n", p2[0], p2);
free(p1);
/* remapping virtual addresses */
void *p0 = mremap(p2, 4096, 4096, MREMAP_MAYMOVE | MREMAP_FIXED, p1);
/* checking */
printf("p0 is %c at address %p\n", p0[c], p0);
return 0;
}
预期产出:
p1是位于xxx的地址
p2是地址yyy处的b
p0在地址xxx处为b由
malloc()
返回的地址可能没有页面对齐,因此mremap()
正在将errno
设置为EINVAL
。如果我使用mmap()
而不是malloc()
,并修复代码中的语法错误:
#define _GNU_SOURCE 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
int main(void) {
char *p1 = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
memset(p1, 'a', 4096);
char *p2 = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
memset(p2, 'b', 4096);
printf("p1 is %c at address %p\n", p1[0], (void *)p1);
printf("p2 is %c at address %p\n", p2[0], (void *)p2);
void *p0 = mremap(p2, 4096, 4096, MREMAP_MAYMOVE | MREMAP_FIXED, p1);
if ( p0 == MAP_FAILED ) {
perror("mremap: mremap failed");
return EXIT_FAILURE;
}
printf("p0 is %c at address %p\n", ((char *)p0)[0], p0);
return EXIT_SUCCESS;
}
malloc()
返回的地址可能没有页面对齐,因此mremap()
正在将errno
设置为EINVAL
。如果我使用mmap()
而不是malloc()
,并修复代码中的语法错误:
#define _GNU_SOURCE 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
int main(void) {
char *p1 = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
memset(p1, 'a', 4096);
char *p2 = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
memset(p2, 'b', 4096);
printf("p1 is %c at address %p\n", p1[0], (void *)p1);
printf("p2 is %c at address %p\n", p2[0], (void *)p2);
void *p0 = mremap(p2, 4096, 4096, MREMAP_MAYMOVE | MREMAP_FIXED, p1);
if ( p0 == MAP_FAILED ) {
perror("mremap: mremap failed");
return EXIT_FAILURE;
}
printf("p0 is %c at address %p\n", ((char *)p0)[0], p0);
return EXIT_SUCCESS;
}
从手册页:“如果指定了MREMAP_FIXED,则还必须指定MREMAP_MAYMOVE。”是否可能需要按位&而不是|?@cecilg23:它们都已指定。按位
|
组合位标志是正确的-按位和
通常会为您提供零。从手册页:“如果指定了MREMAP_FIXED,那么还必须指定MREMAP_MAYMOVE。”是否可能需要按位&而不是|?@cecilg23:它们都是指定的。按位|
组合位标志是正确的-按位&
通常为零。谢谢。快速提问,在释放(取消映射)p1之前,怎么可能重新映射到p1?因为C让你做各种事情。我不一定推荐这是个好主意,只是使用mmap()
作为获取页面对齐地址的方便方法。hmmm所以这基本上覆盖了p1指向的虚拟页面的页面表条目和p2指向的物理页面。我懂了。谢谢。这真的很有帮助。你必须重新映射,而不必先取消映射那里的内容,除非你对程序中运行的每一段代码都有高度的控制。如果先取消映射,地址范围将不再属于您,并且您可能会在以后执行重新映射时删除分配的其他内容。谢谢。快速提问,在释放(取消映射)p1之前,怎么可能重新映射到p1?因为C让你做各种事情。我不一定推荐这是个好主意,只是使用mmap()
作为获取页面对齐地址的方便方法。hmmm所以这基本上覆盖了p1指向的虚拟页面的页面表条目和p2指向的物理页面。我懂了。谢谢。这真的很有帮助。你必须重新映射,而不必先取消映射那里的内容,除非你对程序中运行的每一段代码都有高度的控制。如果首先取消映射,地址范围将不再属于您,并且您可能会在以后执行重新映射时删除分配的其他内容。