Page 507 - 《软件学报》2024年第4期
P. 507
欧阳湘臻 等: 榫卯: 一种可组合的定制化内存分配框架 2085
卯内存框架当前提供的可用层级函数如表 2 所示. 其中系统接口层抽象了管理用户堆的方式, 它能将 mmap, brk,
virtualAlloc 等操作系统相关的接口抽象, 以提供更好的跨平台移植性. 同时, 系统接口层也允许在无操作系统的嵌
入式平台上使用预定义的静态内存池来管理现有内存. 基础层分为主干和附加两类, 其中主干部分是构成内存分
配器的主体, 它抽象了内存分配所使用的算法, 如 slab(slab_lk), 伙伴系统 (buddy_glk) 和 TLSF(tlsf_glk). 基础层还
包括一些实现较为简单的附加层, 其中有提供额外分配约束的层级, 如内存对齐分配的 aligned 层, 负责将用户传
入的内存请求上下文中的大小对齐到指定大小; 也有改善性能的附加层, 如改善 CPU cache 局部性的线程缓存
thread_cache 与核心感知的缓存的 carrcache_lk, 以及改善 TLB 局部性的 slab_arrcache. 附加层也可以在非内存安
全的应用场景下提升系统健壮性, 例如检测缓冲区溢出漏洞的 tail_chksum, 以及检测释放后使用行为的 delayed_free;
还有额外的附加层提供条件绕过机制, 允许线程在满足条件的情况下绕过上一层进行内存分配, 以提供更灵活的
组合.
表 2 榫卯内存分配框架的层级函数
分类 层级函数 说明
mmap_heap 使用UNIX mmap接口
brk_heap 使用C库brk接口
系统接口层 virtalloc_heap 使用virtualAlloc接口
sheap_glk 可配置的静态内存堆
malloc_heap 使用C库malloc接口
slab_lk slab式, 每大小阶锁
buddy_glk 伙伴系统, 全局锁
tlsf_glk TLSF, 全局锁
基础层 (主干)
segfit_lk 分离适配, 每大小阶锁
segfit_lf 分离适配, 无锁同步
slab_wf slab式, 无等待同步
aligned 分配大小对齐
batched_free 批量释放缓存层
thread_cache 每线程缓存, 使用LIFO链表管理
carrcache_lk 每CPU核心缓存, 使用缓存数组管理
tarrcache 每线程缓存, 使用缓存数组管理
基础层 (附加) szcls_stat 统计该层以上内存请求大小阶分布
wcet_stat 统计该层以上内存请求延迟分布
perf_stat 统计该层以上内存请求平均时间
tail_chksum 内存块末尾增加校验和
delayed_free 内存块头部增加校验与延迟释放
cond_bypass 可自定义判断条件, 绕过上层进行分配
malloc_socket malloc.h中定义的malloc(3)接口
kernel_socket Linux内核内存分配接口
用户接口层
cmalloc_socket 额外传入核心ID的malloc(3)接口
custom_socket 可自定义入参的malloc(3)接口
此外, 一些附加层也可以记录额外的性能信息或者调试信息, 如统计内存请求大小阶分布的 szclas_stat 和最
差情况请求时间分布的 wcet_stat, 能够在运行时统计并记录信息以便系统的后续优化. 基础层使用榫卯框架提供
的数据结构实现搭建, 以提高代码的可复用性. 用户接口层定义用户如何与内存分配器交互, 并向上连接基础层.
用户接口层的意义在于实现更多样化的用户接口以适配不同的应用场景. 例如在操作系统内核中定制 page_alloc/
kalloc 接口或者在用户态定制 malloc(3) 接口. 在 CPU 核心感知的应用场景下, 用户可以通过传入额外的 CPU 核