简而言之,我想调整内存大小,但将旧内存放在新内存的中间。
所以我所做的就是利用mmap
初始大小(p1
),mmap
在地址前p1
假装我所做的内存更大,然后把新的指针,如果我有一个创建它mmap
(p3
,mremap
)。该代码似乎可以正常工作,但是我不确定这是否应该做。如果不是,我应该如何创建更多内存并将旧的/当前的内存放在其中?
#include <sys/mman.h>
#include <cstdio>
#include <cstring>
#include <cassert>
#include <cerrno>
int main()
{
auto p1 = (char*) mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (!p1 || p1==(char*)-1)
return -1;
auto p1_32 = (int *)p1;
memset(p1, 0, 4096);
p1_32[5] = 1035;
auto p2 = mmap(p1-4096, 4096, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
if (!p2 || p2==(void*)-1)
return -2;
auto p2_32 = (int *)p2;
memset(p2, 0, 4096);
p2_32[5] = 5301;
assert(p2_32[1024+5] == 1035);
auto p3 = mremap(p2, 4096*2, 4096*4, MREMAP_MAYMOVE);
if (p3==(char*)-1)
{
printf("Errno %d\n", errno);
return -2;
}
auto p3_32 = (int*)p3;
assert(p3_32[5] == 5301);
assert(p3_32[1024+5] == 1035);
printf("Is this correct?\n");
return 0;
}
如上所述这里
该
munmap()
功能将删除整个页面的所有映射,这些映射包含进程地址空间的任何部分,从字节开始addr
并继续len
字节。
因此可以通过一次munmap
调用删除多个映射(就像是单个映射一样)。
但是,您的代码存在问题:如何知道是否未使用页面(p2
)之前的页面(p1
)?程序的其他参数(包括malloc
)可能已经分配了它,通过这样使用,MAP_FIXED
您将重写(重新映射)其内容:
MAP_FIXED
在flags参数中设置了when时,将通知实现,pa的值应为addr
。如果MAP_FIXED
设置为,则mmap()
可以返回MAP_FAILED
并设置errno
为[EINVAL]
。如果MAP_FIXED
请求成功,则由建立的映射mmap()
将替换range内该进程页面的所有先前映射[pa,pa+len)
。
因此,我认为这种技巧在一般情况下不会有用,您应该使用它mremap
。
至于实现的方式:Linux确实合并了顺序私有匿名映射,因此两者都将被合并到vma_struct
内核中的一个中。此“功能”具有不良的副作用,例如munmap
无法使用释放内存ENOMEM
。但这更多是实现细节,而不是您可以控制的东西。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句