菜宝钱包(caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。
学习的 ppt
谢谢 AngelBoy1
地址
基础
在macOS中行使的是 libcmalloc
在这个模式中 堆块对应为 tiny *** all large
- tiny (Q = 16) ( tiny < 1009B )
- *** all (Q = 512) ( 1008B < *** all < 127KB )
- large ( 127KB < large )
每个magazine有个cache区域可以用来快速分配释放堆。
quantum
tiny
可以称为 block
在 Tiny 内存堆块中,最小的单元为
quantum` 巨细0x10 字节。
纪录堆块巨细的信息为 以quantum
为单元的 msize
我们malloc 分配的 chunk 由许多的 block
组成
没有 被分配使用的 block
内里是没有元数据 (metadata)的
*** all
*** all 中 这 block 在 region 中的 巨细为 0x200
也被成为 quantum
没有 被分配使用的 block
内里是没有元数据 (metadata)的
结构剖析
每个历程包罗3个区域,划分为tiny rack, *** all rack, large allocations
每个区域内里包罗了 多个 magazine区域
是流动可变的。
magazine区域
中又有多个 Region
对于 tiny rack
1MB 和 *** all rack
8MB他们的巨细差异
“Region”中包罗三样器械,一个是以Q为单元的内存block, 另有个是认真将各个”Region”关联起来的trailer另外一个就是纪录chunk信息的metadata
源码中对应的结构
tiny Region { Q(1Q = 16) * 64520个 region_trailer_t trailer metadata[64520/sizeof(uint32_t)] { bitmaps[0]: uint32_t header = 形貌哪个block是起始chunk bitmaps[1]: uint32_t inuse = 形貌chunk状态(busy/free) } } Small Region { Q(1Q = 512) * 16320个 region_trailer_t trailer metadata[16320] { bitmaps[0]: uint16_t msize = 更高一位形貌chunk状态(busy/free), 其余位形貌chunk的Q值(Q值代表与下一个chunk相差若干个Q) } }
tiny
Tiny 对照类似于 linux 下的堆块
tiny chunk
Free 后会被放在对应的 freelist 上
当 tiny 堆块被 free 后会在堆块内写入数据
由于申请的 chunk 是 0x10 巨细的单元 ,以是 末尾都是 0 右移不会影响恢复。
更高以为 0-0xf 内里随便值
checksum(prev_pointer), checksum(next_pointer), msize
这里虽然和 linux 一样保留在 freelist 然则free 后的 chunk 中保留的却不是 原始的 上一个或者下一个chunk的地址 而是经由 checksum 盘算的 chunk地址。
算法为
Checksum = SumofEverybytes(ptr^cookie)&0xf
会随机天生一个cookie,这个cookie会pointer举行下面的盘算天生一个checksum, 然后将(checksum << 56 ) | (pointer >> 4)运算后将checksum保留在高位上,以便检测堆的元数据是否被溢出损坏
保留的指针的结构
在 free 后的chunk结构中
Msize 纪录的是 block
的个数,好比这个 chunk 巨细为 0x40 那么他对应 4个 block
以是 Msize
的值为 4
tiny magazine
结构
这里的 map_last 类似于一个缓存,对于free 的chunk(<=0x100) 不会直接返回给盘算机,而是先保留在 这个地方,当下次申请的试试优先使用他,在free 下一个 chunk 之后才会将 第一个free 的chunk 真正的free掉。
map_last_free
保留的是 最后一次free 的chunk
map_last_free_msize
保留的是 最后一次free 的chunk的巨细
map_last_free_rgn
保留的是 最后一次free 的chunk region
然后下面的 的才是 我们的 free_list
每个巨细为 0x10 一共有 64 个 free_list
保留在 free_list
上面类似 linux下的 *** allbins
保留方式
tiny Region
tiny Region { Q(1Q = 16) * 64520个 region_trailer_t trailer metadata[64520/sizeof(uint32_t)] { bitmaps[0]: uint32_t header = 形貌哪个block是起始chunk bitmaps[1]: uint32_t inuse = 形貌chunk状态(busy/free) } }
tiny 的 Region
结构图
tiny_header_inuse_pair_t
为8字节 也就是 这个 Region
末尾的 元数据 (matedata)
前4字节 为 Header
用于指示对应的块是不是 chunk 头
后4字节 为 inuse
用于纪录这个chunk 是否被使用
分配机制
分配 tiny 的巨细为 <1008 bytes
当我们申请时,会先去检测
tiny magazine
中tiny_mag_ptr->mag_last_free_msize == msize
是否上一个 free 的chunk 巨细和我们现在要申请的chunk 巨细一样,这个tiny magazine
中的 chunk 类似存储在 缓存中cache
若是
tiny magazine
中的mag_last_free_msize
不相符我们需要的,会去free_list
中找到对应的chunk,然后会 这个 选择的这个chunk->next
指针举行解密。若是 也没用对应巨细的 chunk,回去
free_list
中存在 chunk 且 巨细能够使用的 list 中取出chunk 将chunk 举行切割,取出,然后将剩下的chunk 放入对应 巨细的free_list
中- 若是
free_list
中没有对应的 free 的chunk 能被申请,且tiny region end
巨细知足 申请的chunk巨细 那么就会从tiny region end
中申请 - 当找到对应巨细的 chunk 后,会跟新
metadata(tiny Region 中的 tiny_header_inuse_pair 修改标志位 标明chunk 的使用情形)
然后将申请的 chunk 返回给 用户 。
接着会行使 szone_size
巨细索引方式,验证 头和使用状态。
Free机制
若是free 的chunk 的 mszie < 0x10,当前堆块会与 cache (缓存内里的) 的freeed 堆块交流。
tiny_free_no_lock
类似于 glibc 的堆块合并操作, 合并上一个 和 下一个 freed chunk 然后祛除对应的 inuse 位行使 上一个 freed chunk 末尾的 mszie 来找到上一个 freed chunk 的位置
,
,菜宝钱包(www.caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。
行使 当前chunk 的 mszie 和当前chunk 的更先位置盘算 下一个 freed chunk 的位置
- 在合并之前会举行 unlink 操作。
ulink
unlink 操作的时刻 类似 glibc 然则他是先对 chunk 内里的指针举行 unchecksum
限制也是和 glibc 一样的
ppt 图片注释
首先 我们的 free_list 内里已经存在一个 free了的 chunk 且 我们的 Cache
内里的内容为空
这个时刻我们 free(P) 我们的 P 会被放入到 Cache
内里且纪录当前 free 的 P 的size 和 来自的 Region
接着 我们在 free(Q) 这个时刻由于 P 是在 Cache
内里的,这个时刻 Q 被free 了,我们的 Cache
内里的 P 会被放置到 对应的 free_list,这个时刻这个 free_list 中已经存在一个 free 了的 chunk。
我们要放入 P 入这个 free_list
首先会 检测 free_list 内里的chunk 的 prev header 和 inuse 的元数据位
然后回去 清空 tiny_list
内里 元数据的 P 的 header 和 inuse 位。
然后对 P 和 free_list 内里的chunk 举行unlink 操作,由于是 相邻的,于是举行合并。然后再去检查下一个 chunk举行上面操作。
接着 合并的chunk 会被放到 对应巨细的 free_list 内里
Small
*** all chunk
*** all chunk
结构类似月 tiny chunk 纷歧样的是这里 pre 和 next 指针用的是原始指针
不用的是 pre 和 next 指针不是相邻的 而是 在 pre next 之后 添加一个 字节来储存 checksum 的值
且这个值会被填充为 8 字节
obb free chunk
且另有一种称为 oob free chunk 的 用于实现页面临其。这样的 chunk 中没有 元数据(metadata)
oob_free_entry_s
行使来治理 oob chunk。
Prev 和 next 指向表中同样巨细的 free 的chunk
保留的是 原始数据。
Ptr 是对这个 oob chunk 的标志,oob chunk在 region 内里的索引 和 是否这个 oob 被free(更高位标志)
*** all magzine
前面的基础 和 tiny magazine 一样的
前面的 map_last_xxx
保留上次 free 后放入到 这里的 chunk 也就是 一个 Cache
缓存
这里是 free_list
是以 0x200 字节为单元 保留的值 oob_free_entry 然后凭证 oob_free_entry 的 Ptr 指针找到对应的 free 的chunk 的位置。oob_free_entry
又保留在 *** all Region
的末尾
其中 free_lits 内里存储的 chunk 不会 直指向 magzine
*** all Region
其中保留 chunk
*** all_region_end
*** all_meta_words
*** al_oob_free_entries
block 巨细为 0x200
这个 region
巨细默以为 0x800000
block 的个数为 16319
region 末尾存在 *** all_meta_words
*** all_oob_free_entries
*** all_meta_words
内里保留的元素对应 region 内里的 每个 block
且内里 保留了 chunk 的巨细和 inuse 位
这内里保留的 block 会保留当前使用中的 chunk 的 size 巨细
也会保留 freed chunk 的 巨细和 flag 标志
这个 block 内存的更高一位 标志chunk 是否被使用
*** all_oob_free_entries
一共 32 个保留位置
保留 oob_free_entry
(实现页面临齐)
free 后结构
分配机制
分配巨细 为 1008 - 128kb 行使 *** all_malloc
和 tiny 一样 先去查看
magzine
内里map_last_xxx
(Cache) 是否保留了 对应 msize 的free 的 *** all chunk。若是存在直接取出Cache
内里值保留一个上一次 free 的 chunk若是没有合适的,会去对应的 free_list 内里找。
一样平常情形下的 chunk 会执行 unchecksum next 指正。接着会去检测 双链接表 执行unlink 操作, 判断 next->prev == ptr
和 tiny chunk 的申请是一样的,然则 oob chunk 内里ptr 地址存的是 原始数据 不用挪用 unchecksum
且是从 free_list 头取出
申请获得 chunk 后 会修改
*** all Region
末尾的*** all_oob_free_entries
内里临应的标志 修改 flag|size 为 mszie msize 的巨细为0x600/0x200
这样的盘算
Free机制
把 chunk 放入
Cache
在free *** all chunk 中也会存在 合并操作。
首先凭证这个堆块 prev 指针找到上一个堆块,凭证堆块所在的 Region 末尾的
*** all_meta_words
去查看这个 上一个堆块 标志位,判断这个堆块 是否被free 和 他的msize。从而定位到 上一个chunk 的位置。然后找到 下一个堆块的 判断是否 free 获得他的巨细
接着 合并相邻地址的 prev next free 的chunk (先举行unlink 然后举行 合并
unlink
首先凭证 是否为 oob chunk
若是为 oob chunk 直接获取 对应的 ptr 指正,若是不是先举行 unchecksum
然后举行合并
也是和 tiny chunk 一样会验证 chunk 的 prev->next == next->prev == ptr
确立才回挪用 unlink
图解
和tiny 一样
网友评论
最新评论