mmap是否连续分配堆内存?

时间:2012-11-05 14:44:51

标签: memory-management mmap

提供:

  • 我请求的尺寸是页面尺寸的倍数
  • 我请求的起始地址是最后一次分配的大小+起始地址

如果我在使用mmap在堆上分配内存时总是遵循这些规则,返回的地址是否会连续?或者他们之间可能存在差距吗?

3 个答案:

答案 0 :(得分:3)

您可以使用MAP_FIXED标志获得所需的行为。不幸的是,对于您的目标,它并非普遍支持,因此您需要检查返回值以确保它为您提供所请求的分配。为了获得良好的可移植性,您需要一个备用计划,以便在调用返回0时使用。

答案 1 :(得分:2)

快速回答:不一定。在各种机器的有限广泛测试中它很可能“几乎总能工作”,但绝对不是好的做法。大多数Linux都支持MAP_FIXED标志,但根据我的经验,它也有错误。避免。

在您的情况下,最好只是一次性分配您需要的所有内容,然后手动将指针分配给映射的每个子部分:

int LengthOf_FirstThing = 0x18000;
int LengthOf_SecondThing = 0x10100;
int LengthOf_ThirdThing = 0x20000;

int _pagesize = getpagesize();
int _pagemask = _pagesize - 1;

size_t sizeOfEverything = LengthOf_FirstThing + LengthOf_SecondThing + LengthOf_ThirdThing;
sizeOfEverything = (sizeOfEverything + _pagemask) & ~(_pagemask);

int8_t* result = (int8_t*)mmap(nullptr, sizeOfEverything, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
int8_t* myFirstThing = result;
int8_t* mySecondThing = myFirstThing + LengthOf_FirstThing;
int8_t* myThirdThing = mySecondThing + LengthOf_SecondThing;

这种方法的一个优点还在于您映射的每个事物都不必严格与页面大小对齐。最重要的是,它确保了完全有记忆的记忆。

更长的回答: mmap()的实现可以完全自由地忽略'提示'地址,因此你永远不应该期望地址被尊重。这可能比预期更常见,因为某些实现可能实际上不支持新mmap()的页面大小粒度。它们可能将有效的起始映射限制为16k或64k边界,以帮助减少管理非常大的虚拟地址空间所需的开销。这样的实现总是会忽略一个未与这种边界对齐的mmap()提示。

此外,mmap()根本不从堆中分配内存。堆是创建进程时由C运行时库(glibc on * nix)创建/保留的内存区域。 malloc()和new / delete通常是从堆中提取的唯一函数,以及可能在内部使用malloc / new的任何库。堆本身通常是通过内部调用mmap()来创建和管理的。

答案 2 :(得分:1)

我认为这不是指定的,而是所谓的“实现细节”。即你不应该依赖一种行为或另一种行为,而是假设指针是不透明的而不关心它的确切值。

(也就是说,黑客可以有一个地方和时间。在这种情况下,你需要确切了解你的操作系统的行为。)