前提是:mmap是否连续分配堆内存?
- 大小我请求的页面大小
- 起始地址我要求的倍数的大小+启动最后一个分配
的地址,如果我公司始终遵循这些规则使用mmap在堆上分配内存时,返回的地址是否连续?或者他们之间可能存在差距?
前提是:mmap是否连续分配堆内存?
的地址,如果我公司始终遵循这些规则使用mmap在堆上分配内存时,返回的地址是否连续?或者他们之间可能存在差距?
快速答案:不一定。在有限的各种机器上进行广泛的测试时,它几乎总是能够工作的一个很好的机会,但它绝对不是好的做法。大多数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()来创建和管理。
我认为这不是指定的,而是所谓的“实现细节”。即你不应该依赖于一种行为或另一种行为,而是假设指针是不透明的并且不关心它的确切值。
(这就是说,有可能是黑客的地方和时间。在这种情况下,你需要找出你的操作系统究竟如何运行。)
你可以得到你想要用MAP_FIXED标志的行为。不幸的是,对于你的目标,这不是普遍支持,所以你想检查返回值,以确保它给你你请求的分配。为了便于携带,您需要一个备份计划,以便在通话返回0时返回0.
在哪个操作系统?这些东西取决于操作系统。 –
如果它不是独立于操作系统的,那么我假设我的问题的答案是“否”,因为我想编写可移植代码。 – Matt
“便携”是一个非常广泛的术语。 –