堆内存和平板分配

Sha*_*dra 7 c linux heap malloc memory-management

我很困惑heapfree list.我有几个问题,我对C++如何在C中工作有我自己的理解.如果我错了,请纠正我.

  • 堆内存是否组织为数据块的链表(空闲列表)?
  • 堆内存和空闲列表之间有区别吗?

我对存储分配的理解(开放改进): - 当我们调用malloc时,它会在堆中分配内存,并通过从中选择合适大小的数据块来实现free list:

当malloc返回某个特定的内存块时,它将从空闲列表中删除,并在页表中更新该内存块的物理地址.

当内存free()空闲时,数据块被插回到空闲列表中,并且可能减少碎片,与相邻块结合,并present清除页表条目中的位.

所以整个堆是一个空闲列表(空闲块的链表)+分配的数据块.

这是存储分配的全面情况吗?

编辑:来自Linux内核开发(Robert Love)关于内存管理,平板分配的章节

"一个空闲列表包含一个可用的,已经分配的数据结构块.当代码需要一个新的数据结构实例时,它可以从空闲列表中获取一个结构,而不是分配足够的内存并设置它对于数据结构.后来,当不再需要数据结构时,它将返回到空闲列表而不是解除分配.从这个意义上说,空闲列表充当对象缓存,缓存经常使用的对象类型."

自由列表被称为"可用,分配的数据结构块".

  • 当它在免费列表中时如何分配
  • 如何将一块内存返回到空闲列表_ 而不是与解除分配该块一样?
  • slab分配与存储分配有何不同

Wyz*_*a-- 7

malloc()与页表并不真正相关; 它分配虚拟地址,内核负责跟踪页面实际存储在物理RAM或磁盘上的位置.

malloc()通过brk()系统调用与内核交互,系统调用要求内核为进程分配更多页面,或者将页面释放回内核.所以实际上有两个级别的内存分配:

  • 内核将页面分配给进程,使这些页面不可供其他进程使用.从内核的角度来看,页面可以位于任何位置,页面表可以跟踪它们的位置,但从进程的角度来看,它是一个连续的虚拟地址空间.操作的"程序中断" brk()是内核允许您访问的地址之间的边界(因为它们对应于已分配的页面)以及如果您尝试访问它们将导致分段错误的地址.
  • malloc()分配程序数据段的可变大小部分以供程序使用.当数据段的当前大小内没有足够的可用空间时,它用于brk()从内核获取更多页面,从而使数据段更大.当它发现数据段末尾的某些空间未被使用时,它用于brk()将未使用的页面返回给内核,从而使数据段更小.

请注意,即使在该进程中运行的程序实际上没有使用任何页面,也可以将页面分配给进程(由内核).如果您free()是位于数据段中间的内存块,则实现free()不能用于brk()收缩数据段,因为在更高的地址处仍有其他已分配的块.因此,从内核的角度来看,页面仍然分配给您的程序,即使它们从" malloc()立场"开始就是"自由空间" .

你对自由列表如何工作的描述听起来对我来说是正确的,尽管我不是如何实现内存分配器的专家.但是你从Robert Love发布的引用听起来就像是在谈论Linux内核中的内存分配,这与malloc()用户空间进程内的内存分配无关.这种免费列表可能有不同的作用.

  • (不知何故,当尝试将其添加到上一个注释时失败时,时间变得混乱.)Wyzard:几年前我用调试钩子编写了一个`malloc()`实现.我很快发现,当您在数据段末尾有未使用的数据时,您不希望将"brk()"内存返回到内核.如果你的程序是在一堆`malloc()的循环中运行,然后是一堆`free()`,那么你将进行不必要的系统调用.当然,`malloc()`的操作系统强度实现可能有优化来处理这种情况. (2认同)