linux动态内存分配

目的

  • 熟悉堆内存布局
  • 了解glibc(ptmalloc2)堆管理机制

目录

内存管理函数

虚拟内存布局


图片来源:sploitfun

mmap&munmap

系统调用

brk&sbrk

系统调用

brk()参数为一个地址,把该地址作为堆底。
sbrk()参数为相对堆底的偏移,并把偏移后函数的返回值作为堆底。
sbrk(0)返回当前堆底地址。

brk()mmap()申请虚拟空间时候的不同:

  • brk(): 改变进程堆的大小;mmap(): 为文件创建一个内存映射(或匿名内存映射),扩大进程的地址空间。
  • brk()分配的虚拟内存在random brk offset的上方(高地址一端,对应图中program break brk处),random brk offset的低地址端紧挨着bss段。mmap()分配的虚拟内存的地址则位于某一处区域,不特意指定并不会在random brk offset附近。

一个例子:




malloc&free

非系统调用

malloc()是通过调用brk()mmap()实现的,当

  • 分配内存大于 128k ,调用 mmap() ,在文件映射区域中分配匿名虚存空间
  • 与bss段相邻的区域没有足够空间来申请新的内存区域
  • 非main thread申请新的内存区域

调用的是mmap(),否则brk(old_brk+length)来申请新的内存区域。

free()是通过brk()munmap()系统调用实现的。

应用程序动态申请内存


allocator的使用可以避免频繁的系统调用操作,同时还有以下特性:

  • 处理任意请求序列
  • 立即相应请求
  • 只使用堆
  • 对齐块
  • 不修改已分配的块

一个例子:

glibc堆管理机制

heap_info——heap header

来源:glibc2.27/malloc/arena.c

malloc_state——arena header

来源:glibc2.27/malloc/malloc.c

malloc_state成员

  • top chunk是arena高地址处的一个chunk,当所有bin都无法满足分配要求时便判断top chunk的大小是否符合分配要求,若满足则拆分top chunk为新分配的空间和新的top chunk;否则,进行堆拓展。
  • last remainder chunk是当请求一个small chunk而small bins和unsorted bins均无符合要求的chunk时由binmaps遍历bin寻找最合适的chunk,切分该chunk时如有剩余则作为新chunk加入unsorted bin,此时便成为last remainder chunk。当再次申请small chunk且small bins无合适chunk则搜索unsorted bin,若恰好last remainder chunk满足分配要求则对其切分,若有剩余那么剩余部分作为新的unsorted bins中的last remainder chunk。

bin

  • fastbins
    • 16~64B(for 32bit);32~128B(for 64bit)
    • LIFO;单链表
    • 不合并
  • bins
    • 循环双链表
    • bin1 – unsorted bin
      • free small chunk和free large chunk暂时添加到unsorted bin
    • bin2 to bin63 – small bin
      • 16,24,32,…,508 bytes(for 32bit),每个bin的chunk大小相同
    • bin64 to bin126 – large bin
      • >=512 bytes(for 32bit)

malloc_chunk——chunk header

来源:glibc2.27/malloc/malloc.c

consolidate

针对non mapped chunks

consolidate forward

  • if PREV_INUSE is set:
    • p->next is a top chunk:
      1. p->size += nextsize
      2. 当前chunk p成为新top chunk
    • p->next is not a top chunk:
      • p->next->next->PRE_INUSE is set:
        1. p->size += p->next->size
        2. unlink
        3. move into unsorted bins

consolidate backward

  • if PREV_INUSE is set:
    1. p->size += p->prev->size
    2. unlink
    3. move into unsorted bins

unlink

其中:

  • 3~4行对p->next->size和p->size进行一致性检查
  • 8~9和17~19行对即将unlink的chunk进行防伪造检查

参考:

Leave a Comment

电子邮件地址不会被公开。 必填项已用*标注