【问题标题】:not all malloc'ed memory is "heap" and each block is not contiguous in virtual memory?并非所有 malloc 的内存都是“堆”并且每个块在虚拟内存中不连续?
【发布时间】:2021-01-10 07:11:15
【问题描述】:

似乎malloc 在内部调用mmap 为:

//not 100% correct onlyfor demo purpose
// void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);

void *malloc(size_t size){
  ...
  mmap(NULL, size,...);   
  ...           
}

所以mallocNULL作为第一个参数传递给mmap作为起始地址,所以内核会为映射选择一个合适的虚拟地址,这意味着malloc不一定会在堆中创建映射区域(由brk 指针指示)。

如果这是真的,这意味着在多次malloc 调用之后,虚拟内存中的每个块之间会有很多间隙,因为每个malloc 返回一个与前一个不连续的新虚拟地址,而那些虚拟地址地址与brk无关,所以一旦我们释放了一个特定的块,那么我们就不能将相邻的空闲块与我们释放的块合并,因为每个块在虚拟内存中不连续,那么这种动态内存分配是不是非常低效?

【问题讨论】:

  • 您的 64 位 CPU 有多少 TB 的内存?一个 64 位 CPU 可以寻址多少地址空间?假设您只有 16 TiB 的内存;它使用了可能的地址空间的 1/1024(小于 0.1%)。你暂时不会遇到问题。如果你只有 16 GiB 的内存,你说的是 16 TiB 机器使用的空间的 1/1024 - 你使用的地址空间甚至更小。
  • “堆”是一个逻辑概念-您发布的图表将通过brk/sbrk 从操作系统获得的实际内存与“堆”的逻辑概念混为一谈。 “堆”内存是实现想要用来满足对malloc()calloc() 等的调用的任何内存。例如,Hoard memory allocator 为其“堆”使用多个内存池。

标签: c linux dynamic-memory-allocation virtual-memory


【解决方案1】:

malloc 中为大块 使用mmap 的原因正是当块被释放时,它可以被OS 回收,而它是@ 987654323@ped。

这与标准 brk/sbrk“堆”不同,在该“堆”中,几乎不可能移动程序崩溃,只是因为堆的使用正是因为分配/解除分配不需要以精确的 LIFO 顺序发生- 那么你唯一的希望就是尝试合并相邻的空闲内存块......

【讨论】:

  • AAntti Haapala 感谢您的出色回答,我想我快到了。所以我发现对于小分配,malloc 在内部调用 brk,对于大分配,malloc 在内部调用 mmap,这对我来说现在很有意义。但是当我们调用free 来取消分配一个块时,分配器怎么知道这个块最初是从mmapbrk 获得的呢?因为我认为分配器需要区分它们
  • @slowjams — 分配代码跟踪内存块,并知道哪些内存分配给mmap(),哪些分配给sbrk()(或brk())。
  • @JonathanLeffler 感谢您的回答。所以只是为了确认一下,free 在内部分别调用munmapbrk 以获得从mmapbrk 获得的块?
  • 通常情况下,它可以为使用mmap()分配的块调用munmap(),但它不能将内存释放回通过brk()sbrk()分配的o/s。
猜你喜欢
  • 2011-09-29
  • 2014-03-28
  • 2010-10-12
  • 2015-09-16
  • 1970-01-01
  • 2016-09-22
  • 2013-06-24
相关资源
最近更新 更多