MIT6.828LAB2 (1)

LAB2_Part 1 Physical Page Management


前言

记录一下自己的学习过程
实验内容翻译:
https://gitee.com/cherrydance/mit6.828
该翻译仅供参考

首先备份lab1。然后如下图所示执行,得到lab2
在这里插入图片描述

练习1

在文件 kern/pmap.c 中,您需要按照给定的顺序实现以下函数的代码。
boot_alloc()
mem_init()(仅限到调用 check_page_free_list(1) 的部分)
page_init()
page_alloc()
page_free()
check_page_free_list() 和 check_page_alloc() 用于测试您的物理页面分配器。您应该启动 JOS 并查看 check_page_alloc() 是否报告成功。修改您的代码,使其通过测试。您可以添加自己的 assert() 来验证您的假设是否正确。

首先我们在init.c中找到i386_init()函数,里面调用了mem_init(),进入此函数发现它先调用了boot_alloc()函数来创造一个初始页目录。该函数也是要求我们补全的第一个函数。
先看给出的注释和提示告诉我们要实现什么功能。

	// Allocate a chunk large enough to hold 'n' bytes, then update
	// nextfree.  Make sure nextfree is kept aligned
	// to a multiple of PGSIZE.
	//分配足够大以容纳'n'字节的块,然后更新nextfree。
	//确保将nextfree保持对PGSIZE的倍数对齐。

实现代码如下

	result = nextfree;
	nextfree = ROUNDUP(nextfree + n, PGSIZE);
	if((uint32_t)nextfree - KERNBASE > (npages * PGSIZE)){
		panic("out of memory!\n");
	}
	return result;

在memlayout.h和pamp.c的开头给出了一些关键信息,所有物理内存映射到KERNBASE地址上。

//pmap.c
size_t npages;			// Amount of physical memory (in pages)
//memlayout.h
// All physical memory mapped at this address
#define	KERNBASE	0xF0000000

在mem_init函数中继续往下看,

	// Allocate an array of npages 'struct PageInfo's and store it in 'pages'.
	// The kernel uses this array to keep track of physical pages: for
	// each physical page, there is a corresponding struct PageInfo in this
	// array.  'npages' is the number of physical pages in memory.  Use memset
	// to initialize all fields of each struct PageInfo to 0.

意思是让我们分配一块内存存放一个PageInfo的结构体数组将其存储在pages中。这块内存的大小为npages * sizeof(struct PageInfo),并将所有内存初始化为0。
实现代码如下:

	pages = (struct PageInfo*) boot_alloc(npages * sizeof(struct PageInfo));
	memset(pages, 0, npages * sizeof(struct  PageInfo));

接下来是page_init()函数。其要求如下:

	//  1) Mark physical page 0 as in use.
	//     This way we preserve the real-mode IDT and BIOS structures
	//     in case we ever need them.  (Currently we don't, but...)
	//  2) The rest of base memory, [PGSIZE, npages_basemem * PGSIZE)
	//     is free.
	//  3) Then comes the IO hole [IOPHYSMEM, EXTPHYSMEM), which must
	//     never be allocated.
	//  4) Then extended memory [EXTPHYSMEM, ...).
	//     Some of it is in use, some is free. Where is the kernel
	//     in physical memory?  Which pages are already in use for
	//     page tables and other data structures?

总结就是pages[0]默认占用,[IOPHYSMEM, EXTPHYSMEM)占用,在boot_alloc中已经分配的占用,剩下的全是空闲的。实现代码:

	size_t i;
	size_t io_pagenum = (EXTPHYSMEM - IOPHYSMEM) / PGSIZE;
	size_t allo_pagenum = ((uint32_t)boot_alloc(0) - KERNBASE) / PGSIZE;
	for (i = 0; i < npages; i++) {
		if(i == 0){
		//条件1
			pages[i].pp_ref = 1;
		}else if(i >= npages_basemem && i <(npages_basemem + io_pagenum + allo_pagenum)){
		//条件3和条件4
			pages[i].pp_ref = 1;
		}else{
			pages[i].pp_ref = 0;
			pages[i].pp_link = page_free_list;
			page_free_list = &pages[i];
		}		
	}

接下来是实现page_alloc()函数,同样的我们先看给出的提示:

// Allocates a physical page.  If (alloc_flags & ALLOC_ZERO), fills the entire
// returned physical page with '\0' bytes.  Does NOT increment the reference
// count of the page - the caller must do these if necessary (either explicitly
// or via page_insert).
//
// Be sure to set the pp_link field of the allocated page to NULL so
// page_free can check for double-free bugs.
//
// Returns NULL if out of free memory.
//
// Hint: use page2kva and memset

分配一个物理页,如果(alloc_flags & ALLOC_ZERO),怎将整个页面填充为0。
不增加页面的引用计数且将pp_link设置为NULL。如果超出空闲内存返回NULL。
提示的page2kav函数接收一个页面地址,将其转化为内核虚拟地址。
实现代码如下:

struct PageInfo *
page_alloc(int alloc_flags)
{
	// Fill this function in
	struct PageInfo *temp;
	if(page_free_list == NULL){
		//没有可分配的页面
		return NULL;
	}
	temp = page_free_list;
	page_free_list = temp->pp_link;
	temp->pp_link = NULL;
	//从free链表中取出第一个节点的操作
	if(alloc_flags & ALLOC_ZERO){
		memset(page2kva(temp), 0, PGSIZE);
	}
	return temp;
}

最后一个函数是page_free函数。

// Return a page to the free list.
// (This function should only be called when pp->pp_ref reaches 0.)

这个函数的作用就是将一个使用完成的页面进行回收,将其重新放回page_free_list链表中。其代码如下:

	if(pp->pp_ref != 0 || pp->pp_link != NULL){
		panic("page_free error!\n");
	}
	pp->pp_link = page_free_list;
	page_free_list = pp;

将mem_init函数中panic注释,make qemu查看结果:
在这里插入图片描述
可以看到check_page_free_list和check_page_alloc成功。

总结

lab2的part1完成。总的来说倒是不难,根据注释写代码,注意细节。
有问题欢迎大家指出。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值