内存管理-伙伴系统合并块计算,__find_buddy_pfn,谁是我的伙伴???
开始
用1-7块添加到伙伴举例,其实并不明白这里面的数学内容或算法,仅仅是发现伙伴系统合并块的查找和内存碎片减少有关,伙伴系统的合并不是两个空闲块相连就可以随便合并的
__find_buddy_pfn
用于计算一个页的伙伴是谁,这里的位置是free
页的时候,计算伙伴在哪,如果伙伴和当前块的阶一致,也空闲,则合并
/root/qemu/linux-5.10.202/mm/page_alloc.c: 1018buddy_pfn = __find_buddy_pfn(pfn, order); // 相邻的伙伴块,按照 ^ (1 << order) 计算
__find_buddy_pfn
函数内容:
/root/qemu/linux-5.10.202/mm/internal.h: 156/** Locate the struct page for both the matching buddy in our* pair (buddy1) and the combined O(n+1) page they form (page).** 1) Any buddy B1 will have an order O twin B2 which satisfies* the following equation:* B2 = B1 ^ (1 << O)* For example, if the starting buddy (buddy2) is #8 its order* 1 buddy is #10:* B2 = 8 ^ (1 << 1) = 8 ^ 2 = 10** 2) Any buddy B will have an order O+1 parent P which* satisfies the following equation:* P = B & ~(1 << O)** Assumption: *_mem_map is contiguous at least up to MAX_ORDER*/
static inline unsigned long
__find_buddy_pfn(unsigned long page_pfn, unsigned int order)
{return page_pfn ^ (1 << order);
}
__find_buddy_pfn
__find_buddy_pfn
中有注释,如果是8,1000
,1阶,即两个块,pfn是8,这这个块是8和9两个页
伙伴 = 8 ^ (1 < 1) = 10,也就是和10、11两个页(当前为1阶,这里不判断这两个页是否真的在一介,后面其他函数会判断,如果这两个页在一阶且为空)互为伙伴
伙伴初始化时块的分配规则
/root/qemu/linux-5.10.202/mm/memblock.c: 1900static void __init __free_pages_memory(unsigned long start, unsigned long end) // 伙伴系统初始化,会按照 page 的 pfn 按阶存放 每个阶存档的page地址一定是 2**n 对齐
{int order;while (start < end) {order = min(MAX_ORDER - 1UL, __ffs(start)); // ffs 第一个有 1 的 bit 位置 - 1,相当于根据 pfn 地址确定 orderwhile (start + (1UL << order) > end) // 和 1912 行的 start += (1UL << order); 有联系,如果有连续大块,放到对应 orderorder--;memblock_free_pages(pfn_to_page(start), start, order); // 加入到伙伴系统start += (1UL << order);
下面举例:
举例
加入有1-13,一共12个页要加入伙伴系统
pfn | hex | __ffs | 加入到伙伴的阶 | 解释 |
---|---|---|---|---|
1 | 1 | 0 | 0 | 1 + (1 << 0) <= 13 |
2 | 10 | 1 | 1 | 2 + (1 << 1) <= 13 |
3 | 11 | 1 | 跳过 | 2 += (1 << 1) |
4 | 100 | 2 | 2 | 4 + (1 << 2) <= 13 |
5 | 101 | 2 | 跳过 | 4 += (1 << 2) |
6 | 110 | 2 | 跳过 | 4 += (1 << 2) |
7 | 111 | 2 | 跳过 | 4 += (1 << 2) |
假如3变成了0阶,现在释放了3需要加入的伙伴系统,那么3的伙伴就是2,这两个可能合并为1阶,2的伙伴页同样是3
2 ^ (1 << 0) = 3
3 ^ (1 << 0) = 2
同理,4和5互为在0阶时候的伙伴,4和5可组合到1阶时,可以和6和7组成的1阶合并到2阶
4 ^ (1 << 0) = 5
5 ^ (1 << 0) = 4
4 ^ (1 << 1) = 6 (1阶时伙伴为6,和(6,7)提升到2阶)
6 ^ (1 << 1) = 4