本小节有几个重要的知识点:
- 伙伴系统的思想
- 伙伴系统的实现
- 伙伴系统分配器:内存块的申请、释放过程
- 伙伴算法和阶数
1.伙伴系统的思想
针对某个某个zone分区,(1)把物理地址相连的空闲页连接起来合成一个物理块,因此会在系统中分散着一堆物理块;(2)然后将大小相同的物理块用链表连接起来;(3)用free_area[order] 指向对应的链表。从而初步缓解了内存碎片化。
伙伴系统主要用于管理物理内存,主要管理page。首相将系统中的内存分为大小不同的物理块,对于物理地址相连的物理页合并成大的物理块,对于相同大小的物理块用链表连接起来,通过一个struct free_area free_are[MAX_ORDER]保存,每个元素都指向一个链表(他们内存块大小不一样)。最大物理块是4MB。假如用户正好申请4KB,就直接从块为4KB的链表摘除一块出来,如果正好没有了,就会从8KB的地方拆分2个4KB出来,一个分给用户,另一个交给下一级的链表。相反,如果用户释放内存,如果发现释放后的page和旁边的相连,就会逆向的把它合并在一起。
2.伙伴系统的实现
首先,伙伴系统的实现是基于分区zone的实现的。首先回顾一下zone结构体。伙伴系统主要是指对free_area的管理
free_area[]结构体存放了各个链表的表头。lowmem_reserve还会对内存做一些备份。free_area并不会指向所有的内存,只会把分区的大部分空闲内存放进来。
示例:以下是ubuntu上查看buddyinfo的信息,12列对应的就是ORDER=0-11时的free_area[order]链表上的内存。
3. 新版伙伴系统实现
为了进一步优化内存碎片化,在原来的伙伴系统上,free_area[order]上引入了type的概念。对每个free_area[order]进行分类,观察哪些是可移动的,不可移动的,可回收的,预留的,隔离的以及CMA等等。
问题:如何判断某个页是否被添加到伙伴系统中?
- struct page 结构体中的成员atomic_t _mapcount; 这个_mapcount代表了是否发送了映射。unsigned long private; 表达当前内存块的大小,也就是order。记录着你是从哪个内存块分配出去的,如果是1就表示从第二组内存块分配下来的内存,并且大小是8KB由两个物理页组成的。atomic_t _refcount; 表示页表被引用记录的次数