当前位置:首页 > 内存 > 正文

内存池的实现原理

  • 内存
  • 2024-06-09 04:08:20
  • 4341

一、malloc底层实现及原理

可以按合作伙伴系统或按链表实现

两者都扩展了brk堆的上限

Malloc使用mmap的第二种用法(映射匿名)。

1)当开放空间小于128K时,调用brk()函数。malloc的底层实现是brk()系统调用函数,该函数主要移动_enddata指针(这里是_enddata)。time是指Linux地址空间中堆段的结束地址,而不是数据段的结束地址)。

2)当开辟空间大于128K时,系统调用mmap()函数在虚拟地址空间(堆和栈之间,称为“文件映射区”)寻找一块空间开辟)。

Malloc函数用于动态分配内存。为了减少内存碎片和系统调用的成本,malloc使用内存池。它首先申请一大块内存作为堆区,然后将堆区划分为多个内存块,以块为基本单位。的内存管理。当用户请求内存时,直接从堆区域分配合适的空闲块。Malloc使用隐式链表结构将堆划分为不同大小的连续块,包括已分配块和未分配块。同时,malloc使用显式链表结构来管理所有空闲块,即使用双向链表来连接空闲块,每个空闲块注册一个连续的未分配地址。

分配内存时,Malloc会通过隐式链表遍历所有空闲块,选择符合分配要求的块;当合并内存时,malloc使用边界标记方法,基于每个块的数量。前后块是否已经分配决定是否合并块。

1.空闲存储以空闲链表(升序地址)的形式组织。每个块包含一个长度、一个指向下一个块的指针以及一个指向其存储空间的指针。(因为程序中有些地方可能不是通过malloc调用请求的,所以malloc管理的空间不一定是连续的。)
2当有应用程序请求时,malloc会扫描空闲列表,直到发现一个大文件足够块。到(第一次适应)(因此每次调用malloc时花费的时间并不完全相同)。
3.如果该块与请求的大小匹配,则将其从链表中删除并返回给用户。如果块太大,则分为两部分,最后一部分交给用户,剩余部分留在空闲列表中(改变头信息)。因此,malloc分配一段连续的内存。
4.释放时,首先在空闲链接列表中查找可以插入已释放块的合适位置。如果释放块的任一侧都是空闲块,则将这两个块组合成一个更大的块,以减少内存碎片。

为什么brk、sbrk、mmap都是系统调用,如果每次申请内存的时候都调用的话,每次都会产生一个系统调用,其次会影响性能,所以容易产生碎片,因为堆从低地址到高地址,如果高地址的内存不释放,低地址的内存就无法被回收。
所以malloc采用了内存池管理方式(ptmalloc采用边界标记方式将内存划分为很多块来管理内存分配和回收。为了提高内存函数malloc内存分配的效率,ptmalloc会请求一部分内存当我们申请和释放内存的时候,ptmalloc会预先从操作系统中获取一些内存,并使用一些策略来决定是否在操作系统中回收它,从而允许用户申请和释放更多的内存。高效并避免过多的内存碎片