【发布时间】:2020-03-02 11:11:04
【问题描述】:
简而言之,我想调整内存大小,但将旧内存放在新内存的中间。
所以我所做的是使用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;
}
【问题讨论】:
-
几点注意事项:1) 你不必将
mmap返回的内存归零——它已经被归零了(否则它可能会从另一个进程泄漏敏感信息)。 2) 我认为你应该用linux标记它,因为mremap在某些操作系统上不可用。 -
@StaceyGirl 但是
memset()调用将强制将物理内存实际分配给虚拟地址。在实际访问内存之前不会创建这些映射,如果由于内核必须实际创建内存页面而导致时间关键处理停止,延迟这些映射可能会导致严重的性能问题。 -
@Ctx 在这种情况下,规范要求内存用零填充(如果手册页可以称为规范)。不过嵌入式系统有
MAP_UNINITIALIZED。 -
@AndrewHenle 我认为在这种情况下这并不重要。如果需要避免页面错误,可以使用
MAP_POPULATE专门为此 - 这样做会更快。 -
@AndrewHenle
MAP_ANONYMOUS.