From 5cf26522a591f0b82060c24519e911a0d2fb7651 Mon Sep 17 00:00:00 2001 From: KAAAsS Date: Thu, 13 May 2021 00:18:55 +0800 Subject: [PATCH] finish buddy --- lab2/kernel/mm/buddy.c | 105 +++++++++++++++++++++++++++++++++++++---- note.org | 12 +++++ 2 files changed, 108 insertions(+), 9 deletions(-) diff --git a/lab2/kernel/mm/buddy.c b/lab2/kernel/mm/buddy.c index 88b680b..c8cac33 100644 --- a/lab2/kernel/mm/buddy.c +++ b/lab2/kernel/mm/buddy.c @@ -26,7 +26,7 @@ void init_buddy(struct phys_mem_pool *pool, struct page *start_page, /* Init the free lists */ for (order = 0; order < BUDDY_MAX_ORDER; ++order) { pool->free_lists[order].nr_free = 0; - init_list_head(&(pool->free_lists[order].free_list)); + init_list_head(&(pool->free_lists[order].free_list)); // free lists 初始化为空链表 } /* Clear the page_metadata area. */ @@ -35,17 +35,20 @@ void init_buddy(struct phys_mem_pool *pool, struct page *start_page, /* Init the page_metadata area. */ for (page_idx = 0; page_idx < page_num; ++page_idx) { page = start_page + page_idx; - page->allocated = 1; + page->allocated = 1; // 所有页面初始化为已分配 page->order = 0; } /* Put each physical memory page into the free lists. */ for (page_idx = 0; page_idx < page_num; ++page_idx) { page = start_page + page_idx; - buddy_free_pages(pool, page); + buddy_free_pages(pool, page); // 逐一去配页面以初始化 free lists } } +/* + * 获得页面的伙伴页面 + */ static struct page *get_buddy_chunk(struct phys_mem_pool *pool, struct page *chunk) { u64 chunk_addr; @@ -87,8 +90,31 @@ static struct page *get_buddy_chunk(struct phys_mem_pool *pool, static struct page *split_page(struct phys_mem_pool *pool, u64 order, struct page *page) { // - struct page *split_page = NULL; - return split_page; + struct page *buddy = NULL; + + // 我理解的这个函数:把 page 递归切成 order,返回结果。过程修改的都是未分配区域。 + + // 递归出口 + if (page->order == order) { + return page; + } else if (page->order < order) { + return NULL; + } + // 分裂 + // 删除当前节点 + list_del(&page->node); + pool->free_lists[page->order].nr_free--; + // 降格 + page->order--; + // 找伙伴 + buddy = get_buddy_chunk(pool, page); + buddy->order = page->order; + // 加入 free list + list_add(&page->node, &pool->free_lists[page->order].free_list); + list_add(&buddy->node, &pool->free_lists[page->order].free_list); + pool->free_lists[page->order].nr_free += 2; + // 递归调用 + return split_page(pool, order, page); // } @@ -97,12 +123,29 @@ static struct page *split_page(struct phys_mem_pool *pool, u64 order, * pool @ physical memory structure reserved in the kernel * order @ get the (1< - struct page *page = NULL; + struct page *page = NULL, *free_page = NULL; + + // 找可分配 order + u64 free_order = order; + while (free_order < BUDDY_MAX_ORDER && pool->free_lists[free_order].nr_free == 0) { + free_order++; + } + // 当前无可分配 + if (free_order == BUDDY_MAX_ORDER) { + return NULL; + } + // 有可分配,取一块切分 + free_page = (struct page *) pool->free_lists[free_order].free_list.next; + page = split_page(pool, order, free_page); + // 删除出 free list,分配 + list_del(&page->node); + pool->free_lists[page->order].nr_free--; + page->allocated = true; return page; // @@ -120,8 +163,41 @@ struct page *buddy_get_pages(struct phys_mem_pool *pool, u64 order) { static struct page *merge_page(struct phys_mem_pool *pool, struct page *page) { // - struct page *merge_page = NULL; - return merge_page; + struct page *try_merge = NULL, *buddy = get_buddy_chunk(pool, page); + + // 不存在伙伴、伙伴已分配、order 不同则无法合并 + if (buddy == NULL || buddy->allocated || page->order != buddy->order) { + return NULL; + } + // 如果已经最大 order,则不合并 + if (page->order >= BUDDY_MAX_ORDER - 1) { + return NULL; + } + + // 双方都未分配,可以合并一次 + // 从 free 中删除两个节点 + list_del(&page->node); + list_del(&buddy->node); + pool->free_lists[page->order].nr_free -= 2; + // 选择左侧 page + struct page *t; + if (buddy < page) { + t = page; + page = buddy; + } + // 增加 page 的 order + page->order++; + // 链入上一层空列表 + list_add(&page->node, &pool->free_lists[page->order].free_list); + pool->free_lists[page->order].nr_free++; + // 尝试递归合并 + try_merge = merge_page(pool, page); + if (try_merge != NULL) { + return try_merge; + } + + return page; + // } @@ -135,6 +211,17 @@ static struct page *merge_page(struct phys_mem_pool *pool, struct page *page) { void buddy_free_pages(struct phys_mem_pool *pool, struct page *page) { // + if (!page->allocated) + return; + + // 设置标志 + page->allocated = false; + // 修改 free list + list_add(&page->node, &pool->free_lists[page->order].free_list); + pool->free_lists[page->order].nr_free++; + // 尝试合并当前页面 + merge_page(pool, page); + // } diff --git a/note.org b/note.org index 86cdb27..b0c6817 100644 --- a/note.org +++ b/note.org @@ -94,4 +94,16 @@ LR ** Lab 2 +*** 问题1:哪个文件或代码段中指定了 ChCore 物理内存布局 +**** 编译阶段 + +编译时配置镜像格式的文件为 scripts/linker-aarch64.lds.in + +**** 运行阶段 + +运行阶段在 kernel/mm.c:L70 的 mm_init 设置各个地址 + +*** 练习1 + +基本思路就是回收的时候一路尝试向上合并,分配的时候找一个更大的块然后一路向下分裂。