最近正在学习linux下堆的管理机制,收集了书籍和网络上的资料,以自己的理解做了整理,做个记录。如果有什么不对的地方欢迎指出!

Memory Allocator

常见的内存管理机制

  • dlmalloc:通用分配器
  • ptmalloc2:glibc分配器,继承自dlmalloc,并提供了多线程支持,主要研究对象。
  • jemalloc:Firefox
  • tcmalloc:Chrome
  • 其他:编程语言内存分配及回收,比如python
  • ......

malloc工作机制

第一次调用malloc

内存分配机制

头文件:#include<unistd.h>

  • brk()
  1. 函数原型:int brk(void* end_data_segment)
  2. 功能和作用:用于设置program_break指向的位置。
  • sbrk()
  1. 函数原型:void* sbrk(intptr_t increment)
  2. 功能和作用:同brk(),参数可以是负数。执行成功返回上一次program_break的值,可以设置参数为0返回当前的program_break.
  • mmap()
  1. 功能和作用:当用户申请空间大于等于128kb,也就是0x20000字节时,不再使用brk()进行分配,改为使用mmap()。
  • unmmap()
  1. 功能和作用:堆mmap()申请的空间进行回收。

    内存分配图

  • 主线程的arena就是main_arena,包含start_brk和brk中间的连续内存,当main_arena不够分配时,会使用brk()进行扩展。
  • 子线程arena可以有多片连续内存,但是大小是固定的,不可以扩展,如果不够用的话需要再次调用mmap()来分配。

第二次调用malloc

  • 只要分配的空间不超过128kb,则不会再次向system申请空间,超过时才会调用brk()进行扩展。
  • 即使将main_arena全部free,也不会立即把内存还给操作系统,此时内存由glib进行管理。

chunk

chunk时glibc管理内存的基本单元。主要分为以下几类:

  • alloced chunk:已分配正在使用中的chunk。
  • free chunk:已经free的chunk。
  • top chunk:可以理解为地址的最高处,还没有分配的chunk。
  • last remainder chunk:是为了提高内存分配的局部性。

chunk = chunk header + user data,malloc返回给用户的其实是user data指针,具体如下图:

alloced chunk结构

  • size:本chunk的大小,包括prev,大小为8的整数倍。32位以8字节对齐,最小为0x10。64位以16字节对齐,最小为0x20。其中低三位有特殊含义,分别为N、M、P
  • N位:是否属于主进程。
  • M位:是否由mmap()分配。
  • P位:前一堆块占用标志,1为占用,0为空闲。
  • 当P位为0时,表示前一堆块释放,prev表示前一堆块的大小。当P位为1,表示前一堆块使用,prev表示前一堆块的数据。
  • userdata为输入的数据。
  • 将下一堆块的P位设置为1。

free chunk

  • 其中fd、bk属于链表指针,有特殊用途,后面会讲到。
  • prev_size为当前释放块的大小(包含chunk header)
  • 下一堆块P位通常被设置为0(fastbin除外)。

top chcunk

  • 该堆块位于前两种堆块之后,头部结构与alloced相似
  • size:top chunk还有多少空间可以分配。
  • 重要的是P位:0表示上一堆块处于空闲,1表示上一堆块处于使用状态。主要用于判断free时是否能与上一堆块进行合并(fastbin除外)。

last remainder chunk

  • 在malloc时,如果有比较大的chunk可以分配,会把这个chunk分成两部分,一部分返回给用户,另一部分称为remainder,加入到 unsorted bin,last remainder会记录最近拆分的remainder。这个remainder大小至少要为MINSIZE,否则不能拆分。
  • 当下次malloc时,如果last remainder chunk够大,则重复上一过程。
  • 拆分的情况:fast bin 和 small bin 都没有合适的chunk,同时unsorted bin有且只有一个可拆分的chunk,并且这个chunk 是last remainder。

堆空闲块管理结构bin

当alloced chunk被释放后,会根据大小放入bin或者合并到top chunk 中去。bin的主要作用时加快分配速度,通过链表方式(chunk中的fd和bk指针)进行管理。主要有以下几种,顾名思义:

  • fast bin
  • unsorted bin
  • small bin
  • large bin

fastbinsY:这是一个bin数组,里面有NFASTBINS个fast bin

bins:也是一个bin数组,一共有126个bin,按顺序分别是:

  • bin 1 为unsorted bin
  • bin 2 到 bin 63 为small bin
  • bin 64 到 bin 126 为 large bin

fast bin

  • 这类bin通常申请和释放的堆块都比较小,所以使用单链表结构,LIFO(后进先出)分配策略。
  • 为了速度,fast bin不会进行合并,下一个chunk始终处于使用状态。
  • 在fastbinsY数组里按照从小到大的顺序排列。
  • 以64位为例,fast bin结构如下(大小区间0x200x80,32位为0x100x40):

unsorted bin

  • 一定大小堆块被释放时,在加入small bin 和large bin 之前,会首先加入此bin,可以加快分配速度。使用双链表结构,FIFO(先进先出)分配策略。
  • unsorted bin大小可能是不相同的。
  • 由于使用双链表,一个bin会占用bins的两个元素。fd指向上一个chunk,bk指向下一个。
  • 以64位为例,unsorted bin结构如下(非连续内存,大小无限制):

small bin

  • 同一个small bin里的chunk大小相同,使用双链表结构,FIFO(先进先出)分配策略。
  • 由于fast bin和small bin 有重合部分,在某些情况下会加入到small bin
  • 根据大小分成62个不同的bin,0x20,0x30,0x40...0x80,0x90...1008
  • 以64位为例,small bin结构如下(大小区间:size<0x400byte):

large bin

  • 使用双链表结构,FIFO(先进先出)分配策略。
  • free时bk后面多两个此参数:fd_nextsize、bk_nextsize。分别指向前一个和后一个large chunk。
  • 根据大小分成63个不同的bin,大小不再固定。前32个bin为 0x400+64i,32-48 bin为 0x1380+512j,依此类推。并且会将大的chunk放在前面,小的放在后面,以加快速度。
  • 以64位为例,large bin大小区间:size>=1024byte。32位为:size>=512byte。
  • fd_nextsize和bk_nextsize指针用于指向第一个与自己大小不同的chunk,所以也只有在加入了大小不同的chunk时,这两个指针才会被修改。

随后附上glibc内存管理流程图

看不清楚可以保存下来放大。

Glibc堆管理机制基础的更多相关文章

  1. Glibc堆块的向前向后合并与unlink原理机制探究

    i春秋作家:Bug制造机 原文来自:Glibc堆块的向前向后合并与unlink原理机制探究 玩pwn有一段时间了,最近有点生疏了,调起来都不顺手了,所以读读malloc源码回炉一点一点总结反思下. U ...

  2. Java基础-Java中的堆内存和离堆内存机制

    Java基础-Java中的堆内存和离堆内存机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.

  3. Spring 框架基础(05):事务管理机制,和实现方式

    本文源码:GitHub·点这里 || GitEE·点这里 一.Spring事务管理 1.基础描述 Spring事务管理的本质就是封装了数据库对事务支持的操作,使用JDBC的事务管理机制,就是利用jav ...

  4. 2万字|30张图带你领略glibc内存管理精髓(因为OOM导致了上千万损失)

    前言 大家好,我是雨乐. 5年前,在上家公司的时候,因为进程OOM造成了上千万的损失,当时用了一个月的时间来分析glibc源码,最终将问题彻底解决. 最近在逛知乎的时候,发现不少人有对malloc/f ...

  5. Java虚拟机内存管理机制

    自动内存管理机制 Java虚拟机(JVM)在执行Java程序过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有的区 ...

  6. Windows编程中的堆管理(过于底层,一般不用关心)

    摘要: 本文主要对Windows内存管理中的堆管理技术进行讨论,并简要介绍了堆的创建.内存块的分配与再分配.堆的撤销以及new和delete操作符的使用等内容. 关键词: 堆:堆管理 1 引言 在大多 ...

  7. IOS中内存管理机制浅解

    我们知道在程序运行过程中要创建大量的对象,和其他高级语言类似,在ObjC中对象时存储在堆中的,系统并不会自动释放堆中的内存(注意基本类型是 由系统自己管理的,放在栈上).如果一个对象创建并使用后没有得 ...

  8. 浅析java内存管理机制

    内存管理是计算机编程中的一个重要问题,一般来说,内存管理主要包括内存分配和内存回收两个部分.不同的编程语言有不同的内存管理机制,本文在对比C++和Java语言内存管理机制的不同的基础上,浅析java中 ...

  9. linux与C内存管理机制

    转自知乎专栏:https://zhuanlan.zhihu.com/p/51855842?utm_source=wechat_session&utm_medium=social&utm ...

随机推荐

  1. Flink-v1.12官方网站翻译-P003-Real Time Reporting with the Table API

    利用表格API进行实时报告 Apache Flink提供的Table API是一个统一的.关系型的API,用于批处理和流处理,即在无边界的.实时的流或有边界的.批处理的数据集上以相同的语义执行查询,并 ...

  2. 深度解读.NET5 授权中间件执行策略

    前文提要 2021.1月份我写了一个<这难道不是.NET5 的bug? 在线求锤?>, 讲述了我在实现[全局授权访问+特例匿名访问] 遇到的技术困惑: [特例匿名访问,还是走了认证流程]. ...

  3. Codeforces Round #585 (Div. 2) E. Marbles(状压dp)

    题意:给你一个长度为n的序列 问你需要多少次两两交换 可以让相同的数字在一个区间段 思路:我们可以预处理一个数组cnt[i][j]表示把i放到j前面需要交换多少次 然后二进制枚举后 每次选择一个为1的 ...

  4. cf1291c-Mind Control

    题意:n个数n个人依次取数,每个人只能取第一个数或最后一个数,你可以从一开始控制k个人取最前边或是最后边的数,你排在第m位,能取到的最大的数是多少.所有人取数都是最优策略(不是每次取最大数). 题解: ...

  5. python+fiddler下载vip视频 && ts视频可合并

    如果你只想在线看视频可以去看这篇博客:python实现通过指定浏览器免费观看vip视频  先看一下我们程序运行的结果 我们要解析的接口就是(就是这个"接口+视频地址"可以解析出vi ...

  6. Python实现AES的CBC模式加密和解密过程详解 和 chr() 函数 和 s[a:b:c] 和函数lambda

    1.chr()函数 chr() 用一个范围在 range(256)内的(就是0-255)整数作参数,返回一个对应的字符. 2.s[a:b:c] s=(1,2,3,4,5) 1>. s[a]下标访 ...

  7. hdu4533 威威猫系列故事——晒被子

    Problem Description 因为马拉松初赛中吃鸡腿的题目让不少人抱憾而归,威威猫一直觉得愧对大家,这几天他悄悄搬到直角坐标系里去住了. 生活还要继续,太阳也照常升起,今天,威威猫在第一象限 ...

  8. 牛客编程巅峰赛S1第11场 - 黄金&钻石 C.牛牛找子集 (二分)

    题意:有一\(n\)个数,从中找数构成相同的子集,要求子集元素个数为\(k\),求构成子集个数最多的情况,输出子集(字典序最小). 题解:我们可以对子集的个数二分答案,首先用桶记录每个元素的个数,然后 ...

  9. k8s-0-集群

    Docker回顾 docker容器封装应用程序好处 内核在3.8以上,才能完整使用docker隔离功能(所有centos6不推荐用) Docker容器化封装应用程序缺点 容器编排工具有哪些 一: K8 ...

  10. woj1010 alternate sum 数学 woj1011 Finding Teamates 数学

    title: woj1010 alternate sum 数学 date: 2020-03-10 categories: acm tags: [acm,woj,数学] 一道数学题.简单. 题意 给一个 ...