1、什么是堆?
- 是虚拟地址空间的一块连续的线性区域
- 提供动态分配的内存,允许程序申请大小未知的内存
- 在用户与操作系统之间,作为动态内存管理的中间人
- 响应用户的申请内存请求,向操作系统申请内存,然后将其返回给用户程序
- 管理用户所释放的内存,适时归还给操作系统
2、各种堆管理器
- dlmalloc- General purpose allocator
- ptmalloc2 - glibc(Linux系统使用的libc) 本文重点学习 - jemalloc - FreeBSD and Firefox
- tcmalloc - Google
- libumem - Solaris
堆管理器并非由操作系统实现,而是由libc.so.6链接库实现。封装了一些系统调用,为用户提供方便的动态内存分配接口的同时,力求高效地管理由系统调用申请来的内存。
- 申请内存的系统调用:(子线程只能用mmap,主线程都可以)
- brk(从data向上扩展一段空间作为堆空间)
- mmap(直接调用一段空间作为堆空间)
3、堆管理器是如何工作的?
三个关键字:
- arena
- chunk
- bin
3.1 arena
内存分配区,可以理解为堆管理器所持有的内存池
堆管理器与用户的内存交易发生于arena中
可以理解为堆管理器向操作系统批发来的有冗余的内存库存
3.2 chunk
用户申请内存的单位,也是堆管理器管理内存的基本单位
malloc()返回的指针指向一个chunk的数据区域
chunk在glibc中的实现:
malloced chunk结构:
注意:prev size指得是上一个free_chunk 的大小
free chunk结构:
注意:p =0 指得是上一个chunk为free_chunk,p=1就是上一个chunk写有数据。发现p=0和上面free_chunk进行合并,改动上一个free_chunk的size即可;
3.3 bin
管理arena中空闲chunk的结构
以数组的形式存在,数组元素为相应大小的chunk链表的链表头
存在于arena的malloc_state中
- unsorted bin
- fast bins
- small bins
- large bins
- (tcache)
unsorted bin结构:
保留一些大小不一的杂的free_chunk,注意fd指向下一个chunk,bk指向上一个。 - bins[1]
- 管理刚刚释放还为分类的chunk
- 可以视为空闲chunk回归其所属bin之前的缓冲区
small bins: 多个unsorted bin头两个串起来
- bins[2] ~ bin[63]
- 62个循环双向链表
- FIFO 先进先出
- 管理16、24、32…、504Bytes的free chunks(32位下)
- 每个链表中存储的chunk大小都一致
fast bins结构:
- fastbinsY[]
- 单向列表
- LIFO – 后入先出
- 管理16、24、32、40、48、56、64Bytes的free chunks(32位下默认,64位*2就行)
- 其中的chunk的in_use 位(下一个物理相邻的chunk的P位)总位1,为了不被free chunk合并,更快分配chunk
large bins结构:
- bins[64] ~ bins[126]
- 63个循环双向链表
- FIFO
- 管理大于504Bytes的free chunks(32位下)
malloc_state
3.4 tcache
与fastbin很像,管理还没分配过的一大段free_chunk
4、堆漏洞
有系统的地方就有漏洞:
- UAF
- Buffer Overflow
- Double Free
- Off-by-One
- Unlink
. . . . . .