malloc的底层实现(ptmalloc)

ptmalloc是C运行时库用于内存管理的一种实现,它采用内存池的方式提高内存分配和回收效率。内存布局分为栈、堆和mmap映射区域。malloc主要通过brk和mmap函数进行内存分配,使用主分配区和非主分配区解决多线程锁竞争,通过chunk内存块管理内存。malloc流程包括fast bins、unsorted bins、small bins、large bins和top chunk的查找和分配,而内存回收涉及fast bins、unsorted bins和top chunk的合并及mmap内存的释放。
摘要由CSDN通过智能技术生成

前言

  本文主要介绍了ptmalloc对于内存分配的管理。结合网上的一些文章和个人的理解,对ptmalloc的实现原理做一些总结。

内存布局

  介绍ptmalloc之前,我们先了解一下内存布局,以x86的32位系统为例:
  这里写图片描述
  从上图可以看到,栈至顶向下扩展,堆至底向上扩展, mmap 映射区域至顶向下扩展。 mmap 映射区域和堆相对扩展,直至耗尽虚拟地址空间中的剩余区域,这种结构便于 C 运行时库使用 mmap 映射区域和堆进行内存分配。

brk(sbrk)和mmap函数

  首先,linux系统向用户提供申请的内存有brk(sbrk)和mmap函数。下面我们先来了解一下这几个函数。

brk() 和 sbrk()

#include <unistd.h>
int brk( const void *addr )
void* sbrk ( intptr_t incr );

两者的作用是扩展heap的上界brk
Brk()的参数设置为新的brk上界地址,成功返回1,失败返回0;
Sbrk()的参数为申请内存的大小,返回heap新的上界brk的地址

mmap()

#include <sys/mman.h>
void *mmap(void *addr, size\_t length, int prot, int flags, int fd, off\_t offset);
int munmap(void *addr, size_t length);

Mmap的第一种用法是映射此盘文件到内存中;第二种用法是匿名映射,不映射磁盘文件,而向映射区申请一块内存。
Malloc使用的是mmap的第二种用法(匿名映射)。
Munmap函数用于释放内存。

主分配区和非主分配区

Allocate的内存分配器中,为了解决多线程锁争夺问题,分为主分配区main_area和非主分配区no_main_area。
 1. 主分配区和非主分配区形成一个环形链表进行管理。
 2. 每一个分配区利用互斥锁使线程对于该分配区的访问互斥。
 3. 每个进程只有一个主分配区,也可以允许有多个非主分配区。
 4. ptmalloc根据系统对分配区的争用动态增加分配区的大小,分配区的数量一旦增加,则不会减少。
 5. 主分配区可以使用brk和mmap来分配,而非主分配区只能使用mmap来映射内存块
 6. 申请小内存时会产生很多内存碎片,ptmalloc在整理时也需要对分配区做加锁操作。

当一个线程需要使用malloc分配内存的时候,会先查看该线程的私有变量中是否已经存在一个分配区。若是存在。会尝试对其进行加锁操作。若是加锁成功,就在使用该分配区分配内存,若是失败,就会遍历循环链表中获取一个未加锁的分配区。若是整个链表中都没有未加锁的分配区,则malloc会开辟一个新的分配区,将其加入全局的循环链表并加锁,然后使用该分配区进行内存分配。当释放这块内存时,同样会先获取待释放内存块所在的分配区的锁。若是有其他线程正在使用该分配区,则必须等待其他线程释放该分配区互斥锁之后才能进行释放内存的操作。

Malloc实现原理:

  因为brk、sbrk、mmap都属于系统调用,若每次申请内存,都调用这三个,那么每次都会产生系统调用,影响性能;其次,这样申请的内存容易产生碎片,因为堆是从低地址到高地址,如果高地址的内存没有被释放,低地址的内存就不能被回收。
  
  所以malloc采用的是内存池的管理方式(ptmalloc),Ptmalloc 采用边界标记法将内存划分成很多块,从而对内存的分配与回收进行管理。为了内存分配函数malloc的高效性,ptmalloc会预先向操作系统申请一块内存供用户使用,当我们申请和释放内存的时候,ptmalloc会将这些内存管理起来,并通过一些策略来判断是否将其回收给操作系统。这样做的最大好处就是,使用户申请和释放内存的时候更加高效,避免产生过多的内存碎片。

chunk 内存块的基本组织单元

在 ptmalloc 的实现源码中定义结构体 malloc_chunk 来描述这些块。malloc_chunk 定义如下:


                
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值