边界标记法

  1. /* conversion from malloc headers to user pointers, and back */
  2. #define chunk2mem(p) ((Void_t*)((char*)(p) + 2*SIZE_SZ))
  3. #define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))
  • chunk2mem(p):根据 chunk 地址获得返回给用户的内存地址
  • mem2chunk(mem):根据 mem 地址得到 chunk 地址
  1. /* The smallest possible chunk */
  2. #define MIN_CHUNK_SIZE (offsetof(struct malloc_chunk, fd_nextsize))
  • fd_nextsize 指针距离 malloc_chunk 结构体开头的字节偏移量,也就是最小的chunk的大小。(32 位平台上位 16 字节,64 位平台为 24 字节或是 32 字节。)
  1. /* The smallest size we can malloc is an aligned minimal chunk */
  2. #define MINSIZE \
  3. (unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))
  • 这个式子的含义是求 MIN_CHUNK_SIZE 在 MALLOC_ALIGN_MASK + 1 的最小上界,MALLOC_ALIGN + 1 等于 MALLOC_ALIGNMENT ,所以这个式子的意思便是求满足字节对齐最小的可 malloc 分配的 chunk 。
  1. /* Check if m has acceptable alignment */
  2. #define aligned_OK(m) (((unsigned long)(m) & MALLOC_ALIGN_MASK) == 0)
  3. #define misaligned_chunk(p) \
  4. ((uintptr_t)(MALLOC_ALIGNMENT == 2 * SIZE_SZ ? (p) : chunk2mem (p)) \
  5. & MALLOC_ALIGN_MASK)
  • intptr_t:其长度总是所在平台的位数,用来存放地址。
  • uintptr_t 是intptr_t 的无符号版本。
  • aligned_OK(m):m判断是否对齐
  • misaligned_chunk(p):实现p的对齐
  1. /*
  2. Check if a request is so large that it would wrap around zero when
  3. padded and aligned. To simplify some other code, the bound is made
  4. low enough so that adding MINSIZE will also not wrap around zero.
  5. */
  6. #define REQUEST_OUT_OF_RANGE(req) \
  7. ((unsigned long)(req) >= \
  8. (unsigned long)(INTERNAL_SIZE_T)(-2 * MINSIZE))
  9. /* pad request bytes into a usable size -- internal version */
  10. #define request2size(req) \
  11. (((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
  12. MINSIZE : \
  13. ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
  14. /* Same, except also perform argument check */
  15. #define checked_request2size(req, sz) \
  16. if (REQUEST_OUT_OF_RANGE(req)) { \
  17. MALLOC_FAILURE_ACTION; \
  18. return 0; \
  19. } \
  20. (sz) = request2size(req);
  • REQUEST_OUT_OF_RANGE(req):如果申请大小加上两个最小块大小大于等于 unsigned long 的长度则置 1,否则置 0。
  • request2size(req):将用户请求的大小转换成实际分配的大小,SIZE_SZ是下一个chunk的prev_size域的空间复用。
  • checked_request2size(req, sz):判断申请大小是否溢出,没有溢出的情况下sz记录实际分配的大小。
  1. /* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */
  2. #define PREV_INUSE 0x1
  3. /* extract inuse bit of previous chunk */
  4. #define prev_inuse(p) ((p)->size & PREV_INUSE)
  5. /* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */
  6. #define IS_MMAPPED 0x2
  7. /* check for mmap()'ed chunk */
  8. #define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
  9. /* size field is or'ed with NON_MAIN_ARENA if the chunk was obtained
  10. from a non-main arena. This is only set immediately before handing
  11. the chunk to the user, if necessary. */
  12. #define NON_MAIN_ARENA 0x4
  13. /* check for chunk from non-main arena */
  14. #define chunk_non_main_arena(p) ((p)->size & NON_MAIN_ARENA)
  • prev_inuse(p):为 0 则表示前一个 chunk 为空闲,为 1 表示前一个 chunk 正在使用。
  • chunk_is_mmapped(p):为 1 表示该 chunk 是从 mmap 映射区域分配的,否则是从 heap 区域分配的。
  • chunk_non_main_arena(p):为 1 表示该 chunk 属于非分配区,为 0 表示该 chunk 属于主分配区。
  1. /*
  2. Bits to mask off when extracting size
  3. Note: IS_MMAPPED is intentionally not masked off from size field in
  4. macros for which mmapped chunks should never be seen. This should
  5. cause helpful core dumps to occur if it is tried by accident by
  6. people extending or adapting this malloc.
  7. */
  8. #define SIZE_BITS (PREV_INUSE|IS_MMAPPED|NON_MAIN_ARENA)
  9. /* Get size, ignoring use bits */
  10. #define chunksize(p) ((p)->size & ~(SIZE_BITS))
  11. /* Ptr to next physical malloc_chunk. */
  12. #define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~SIZE_BITS) ))
  13. /* Ptr to previous physical malloc_chunk */
  14. #define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) ))
  15. /* Treat space at ptr + offset as a chunk */
  16. #define chunk_at_offset(p, s) ((mchunkptr)(((char*)(p)) + (s)))
  • chunksize(p):获取size域低3位的值。
  • next_chunk(p):获取下一个chunk的地址。
  • prev_chunk(p):获取上一个chunk的地址。
  • chunk_at_offset(p, s):将 p + s 的地址强制看作一个chunk。
  1. /* extract p's inuse bit */
  2. #define inuse(p)\
  3. ((((mchunkptr)(((char*)(p))+((p)->size & ~SIZE_BITS)))->size) & PREV_INUSE)
  4. /* set/clear chunk as being inuse without otherwise disturbing */
  5. #define set_inuse(p)\
  6. ((mchunkptr)(((char*)(p)) + ((p)->size & ~SIZE_BITS)))->size |= PREV_INUSE
  7. #define clear_inuse(p)\
  8. ((mchunkptr)(((char*)(p)) + ((p)->size & ~SIZE_BITS)))->size &= ~(PREV_INUSE)
  • inuse(p):获取当前 chunk 是否使用的标志位,为 1 正在使用,为 0 chunk 空闲。
  • set_inuse(p):将当前 chunk 的是否使用标志位置 1。
  • clear_inuse(p):将当前 chunk 的是否使用标志位置 0。
  1. /* check/set/clear inuse bits in known places */
  2. #define inuse_bit_at_offset(p, s)\
  3. (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE)
  4. #define set_inuse_bit_at_offset(p, s)\
  5. (((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE)
  6. #define clear_inuse_bit_at_offset(p, s)\
  7. (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE))
  • inuse_bit_at_offset(p, s):获取指定 chunk 的 size 域的使用标志位
  • set_inuse_bit_at_offset(p, s):将指定 chunk 的 size 域的使用标志位置 1。
  • clear_inuse_bit_at_offset(p, s):将指定 chunk 的 size 域的使用标志位置 0。
  1. /* Set size at head, without disturbing its use bit */
  2. #define set_head_size(p, s) ((p)->size = (((p)->size & SIZE_BITS) | (s)))
  3. /* Set size/use field */
  4. #define set_head(p, s) ((p)->size = (s))
  5. /* Set size at footer (only when chunk is not in use) */
  6. #define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_size = (s))
  • set_head_size(p, s):设置当前 chunk p 的 size 域并保留 size 域的控制信息。
  • set_head(p, s):设置当前 chunk p 的 size 域并忽略已有的 size 域控制信息。
  • set_foot(p, s):设置当前 chunk p 的下一个 chunk 的 prev_size 为 s,s 为当前 chunk 的 size,只有当 chunk p 为空闲时才能使用这个宏,当前 chunk 的 foot 的内存空间存在于下一个 chunk,即下一个 chunk 的 prev_size。

内容来源

《Glibc内存管理》

《Glibc内存管理》笔记DAY3的更多相关文章

  1. 《Glibc内存管理》笔记DAY5

    目录 分箱式内存管理 Unsorted bin Fast bins 核心结构体分析 malloc_state 内容来源 分箱式内存管理 Unsorted bin   Unsorted bin 可以看作 ...

  2. 《Glibc内存管理》笔记DAY4

    目录 分箱式内存管理 Small bins Large bins 内容来源 分箱式内存管理   对于空闲的 chunk,ptmalloc 采用分箱式内存管理方式,根据空闲 chunk 的大小和处于的状 ...

  3. 《Glibc内存管理》笔记DAY2

    目录 Ptmalloc内存管理设计 Main_arena 与 non_main_arena chunk 的组织 空闲 chunk 容器 sbrk 与 mmap 内存分配概述 内存回收概述 边界标记法 ...

  4. 《Glibc内存管理》笔记DAY1

    目录 x86_64栈和mmap固定映射地址 内存的延迟分配 内核数据结构 mm_struct Heap 操作相关函数 Mmap 映射区域操作相关函数 内容来源 x86_64栈和mmap固定映射地址   ...

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

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

  6. 读书摘要观后感与总结:《Glibc内存管理:ptmalloc2源代码分析》

    更新中 在Linux平台下做漏洞利用的时候,针对于Heap部分总是有些不求甚解,下面开个博文来记录下<Glibc内存管理:ptmalloc2源代码分析>这本书的读后感和收获,一些简单的点将 ...

  7. glibc内存管理那些事儿

    本文转载自glibc内存管理那些事儿 Linux内存空间简介 32位Linux平台下进程虚拟地址空间分布如下图: 进程虚拟地址空间分布 图中,0xC0000000开始的最高1G空间是内核地址空间,剩下 ...

  8. 黑马程序员_ Objective-c 内存管理笔记

    引用计数器 当一个对象被创建出来,就要分配给内存这个对象,当不用这个对象的时候,就要及时的回收,为了可以明确知道对象有没有被使用,就要用引用计数器来体现,只要计数器不为0,表明对象被使用中. 1.方法 ...

  9. Java内存管理笔记

    java内存管理机制 在java中,内存管理由JVM完全负责,java中的"垃圾回收器"负责自动回收无用对象占据的内存资源,这样可以大大减少程序猿在内存管理上花费的时间,可以更集中 ...

随机推荐

  1. vue复制textarea文本域内容到粘贴板

    vue实现复制内容到粘贴板   方案:找到textarea对象(input同样适用),获取焦点,选中textarea的所有内容,并调用document.execCommand("copy&q ...

  2. JS定时器做物体运动

    JS定时器是函数 setInterval(函数体/函数名  , 时间) 清楚定时器 clearInterval(函数) 时间单位(毫秒) 1000毫秒  = 1秒 首先我们要知道用JS定时器能干什么? ...

  3. Swagger 接口文档规范

    导语: 相信无论是前端还是后端开发,都或多或少地被接口文档折磨过.前端经常抱怨后端给的接口文档与实际情况不一致.后端又觉得编写及维护接口文档会耗费不少精力,经常来不及更新.其实无论是前端调用后端,还是 ...

  4. Android驱动之设备树简介

    目录 一.    设备树简介    2 1.    问题一:为什么需要设备树?    2 ①名词解释:    2 ②DT详细介绍:    2 ③DTS是DT的源文件,描述Device Tree中的设备 ...

  5. mysql安装和遇到的问题处理

    遇到需要在新系统上安装MySQL的事情,简单记录一下过程. 声明:最好的文档是官方文档,我也是看的官方文档,只是中间遇到点问题,记录一下出现的问题和处理方式.贴一些官方文档地址. 用tar包的安装方式 ...

  6. SpringBoot配置HTTPS,并实现HTTP访问自动转HTTPS访问

    [转]https://www.jianshu.com/p/8d4aba3b972d 推荐使用nginx配置https,因本文产生的任何问题不再做回复. 这里说一下为什么写这篇文章,因为我也是一个Spr ...

  7. webpack中bundler源码编写2

    通过第一部分的学习,我们已经可以分析一个js的文件.这节课我们学习Dependencies Graph,也就是依赖图谱.对所有模块进行分析.先分析index.js.index.js里面引入了messg ...

  8. centos下shell脚本kill掉mysql锁表进程【笔记】

    前几天发现服务器上的mysql出现锁表了,show processlist后发现好多都是因为写进session才锁表的,看到这个想起了会不会是硬盘空间不够了,马上查看了服务器硬盘空间,发现都100%了 ...

  9. 备份MySQL数据库并上传到阿里云OSS存储

    1. 环境配置 要将本地文件上传到阿里云oss中, 必须使用阿里云提供的工具 ossutil, 有32位,也有64位的, Linux和Windows都有.具体可以到阿里云官网下载 官网及文档: htt ...

  10. css 移动端页面,在ios中,margin-bottom 没有生效

    在开发中,你会遇到各种美轮美奂的UI交互设计图,下面这种UI图,我在开发时就在布局上遇到一个小问题 问题现象:ios 手机滚动到底部,底部的margin-bottom不生效,Android手机和模拟器 ...