目录
伙伴系统
1、什么是伙伴?
2、伙伴系统的分配原理
3、伙伴系统回收
伙伴系统
1、什么是伙伴?
伙伴必须是大小相同并且在物理上连续的两个或者多个页。
2、伙伴系统的分配原理
- 首先根据内存分配接口函数gfp_t gfp_mask,找到内存分配指定的NUMA节点和物理内存节点zone,然后找到物理内存区域zone对应的伙伴系统。
- 随后内核通过接口中指定的分配阶order,可以定位伙伴系统free_area[order]数组,其中存放的就是分配阶order全部内存块。
- 最后通过gfp_t gfp_mask掩码中指定的页面迁移类型MIGRATE_TYPE,定位到free_list[MIGRATE_TYPE],这里存放的就是符合内存要求的所有内存块。遍历双向链表可以获得要分配的内存。
比如申请2^(order-1),2^order之间内存,类型MIGRATE_MOVABLE时,内核按照2^order进行申请。
- 内核根据order找到伙伴系统中的free_area[order]对应的free_area结构,再根据迁移类型找到free_list[MIGRATE_MOVABLE],如果该迁移类型没有空闲块时,则会进一步到上一级链表free_area[order+1]中寻找,直到找到为止。
- 上一级的页大小是本级的两倍,于是将内存块逐级减半分裂,将每一次分裂后的内存块插到free_area数组里对应的freelist
- 以下是分配一页,order=0 order=1都没有空闲的页,在order=2上分配的一页,示意图
3、伙伴系统回收
释放free_page->free_pages->__free_pages->free_the_page 分为两种情况
- order=0 释放到CUP高速缓存pcplist
- order=1 释放到伙伴系统
释放内存页面的核心功能是把空闲页面添加到伙伴系统中适当的空闲链表中。
- 在释放内存块时,会检查相邻的内存块是否空闲?如果空闲,就将其合并成—个大的内存块,放置到高—级的空闲链表中;
- 如果还能继续合并邻近的内存块,就会继续合并,转移到更高级的空闲链表中;
- 这个过程会一直重复下去,直至所有可能合并的内存块都已经合并。