简而言之,我想调整内存大小,但将旧内存放在新内存的中间。
因此,我所做的是使用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;
}
您的代码有问题:如何知道页面(p2
)之前的页面(p1
)是否未使用?程序的其他参数(包括malloc
)可能已经分配了它,可以像这样使用MAP_FIXED
来rewrite(重新映射)其内容:
当在flags参数中设置
MAP_FIXED
时,实现为告知pa的值应准确为addr
。如果MAP_FIXED
是设置为mmap()
可能会返回MAP_FAILED
并将errno
设置为[EINVAL
]。如果一个MAP_FIXED
请求成功,由mmap()
建立的映射替换范围内流程页面的所有先前映射[pa,pa+len)
。
因此,在一般情况下,我认为此技巧不会有用,应改为使用mremap
。
关于这个问题,Linux确实合并了顺序的私有匿名映射,因此两者都将合并到内核中的单个vma_struct
中。该“特征”具有不良的副作用,例如[CO]。但这更多的是实现细节,而不是您可以控制的东西。