JOS Lab2 Memory Management Part 1 & 2

实验环境

Hardware:
Memory: 		16G
Processor:      Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz × 6
OS Type:        64 bit
Disk:           512GB
Software
OS:             Ubuntu 18.04 LTS(x86_64)
GCC:            gcc 7.5.0  #gcc -v
Make:           GNU Make 4.1  #make --verison
GDB:            GNU gdb 8.1.0  #gdb --version

这个lab主要包括两部分:

  1. 为kernel写一个物理内存分配器
  2. 写一个虚拟内存

准备工作:

运行以下命令以获得最新版本的lab2:

git pull
git checkout -b lab2 origin/lab2

git checkout -b命令做了两件事情:

  1. 它在本地创建了叫lab2的branch,根据远端仓库中的origin/lab2分支
  2. 它将本地lab文件夹中的内容变成lab2分支的内容。

可以使用git checkout branch-name在不同的分支之间切换,注意在不同的分支之间切换之前要先commit修改内容到当前分支之中,否则会丢失。

现在可以把之前在lab1分支中做的修改merge到当前的lab2分支中:

git merge lab1

有时候git可能会merge失败,主要有两种原因:

  1. 同一个文件中既有2个人独自编辑的部分也有共同编辑的部分,merge不知道是谁merge谁
  2. 最新版本的某个文件被删除了,而本地之前的版本还存在这个文件。

解决方法:

  1. 可以使用git checkout --ours保留本地版本
  2. 可以使用git checkout --theirs保留远端版本
  3. 可以git rm删除本地文件再合并

然后再git merge进行合并。

最前面说了一些提醒事项,重要的有如下的内容:
memlayout.h里包括了需要实现的虚拟地址空间布局。pmap.h定义了可以用来跟踪空闲物理内存的PageInfo结构。kclock.ckclock.h用来控制PC时钟和CMOS RAM的。pmap.c需要读这些硬件设备来判断有多少物理内存。
特别注意memlayout.hpmap.h文件,这个lab要求使用并理解里面的内容。同时inc/mmu.h也包括了lab中有用的好多定义。

Part 1: Physical Page Management

这里网站上提到的内容不太多,主要还是需要看代码。网站上说JOS通过页粒度(Page granularity)来管理物理内存,就是把内存分页,通过MMU映射到物理内存,并且用分页机制保护已分配内存。
要写的部分是物理页的分配器。它用一个PageInfo的链表来跟踪空闲页。这里提到了这个链表不是存在空闲页里面的,和xv6不一样。
Exercise 1 要求补全kern/pmap.c中以下函数:

boot_alloc()
mem_init()
page_init()
page_alloc()
page_free()

补完之后启动JOS看能否通过check_page_alloc()函数的测试。
下面我们就来看代码:
首先在memlayout.h里讲了jos的虚拟地址的分布。这部分后面使用到虚拟内存的时候再说。Lab1中告诉了我们物理内存的分布情况,大致如下:

  1. 0x000000000x000A0000的base memory,可用
  2. 0x000A00000x000FFFFF的384KB空间由硬件保留,用作存储BIOS程序等功能,不可用
  3. 0x00100000以上的为extended memory,可用

先看一下调用逻辑有个大概印象。在kern/init.c中首先调用了cons_init()来初始化控制台设备,然后调用了mem_init()完成物理内存的初始化。这是需要在lab2中完成的函数。
回到kern/pmap.c查看需要补全的mem_init()函数。它首先调用了i386_detect_memory()。这个函数用于查看机器有多少物理内存。它初始化了两个全局变量:npages, 机器有多少物理内存页;npages_basemem, base memory包括多少物理页。
接着这个函数调用了boot_alloc()函数为内核页目录kern_pgdir分配了PGSIZE大小的内存,那么我们先来补全boot_alloc().

boot_alloc()

直接来看boot_alloc()提供的代码。代码解释以注释形式给出。

static void *
boot_alloc(uint32_t n)
{
   
	static char *nextfree;	//第一个未使用byte的虚拟地址
	char *result; //函数返回值 
	if (!nextfree) {
   
		extern char end[]; //end是定义在/kern/kernel.ld中定义的符号,位于bss段的末尾,即从内核虚拟地址的末尾开始分配虚拟地址
		nextfree = ROUNDUP((char *) end, PGSIZE);
	}

	
	//这里要求分配足够n byte大小的内存,然后更新nextfree,并且要注意对齐。
	//Your code here:
	return NULL;
}

这里直接连续的往下分配即可。这个函数的补全如下:

	result = nextfree;
	nextfree = ROUNDUP((char*)result + n, PGSIZE);
	
	return result;

继续回到mem_init()往下看。下面它为kern_pgdir分配了虚拟地址空间,然后到了需要我们补充的地方,看下面的要求:

  • 要求分配一列大小为npagesPage Info数组,保存在pages变量中,用memset来初始化这个数组为0.

根据要求补全如下:

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

接着往下,我们已经为初始的内核数据结构分配了空间,然后要着手建立未分配物理页的链表,mem_init()调用了page_init()来完成这件事。

page_init()

原来给了一段代码,但是这段代码把所有的物理页都设置成了空闲,这显然是不对的。我们来看注释的提示:

  1. 把物理页0标记成已用, 这样保存了实模式中断描述符表(real-mode IDT)和BIOS结构,后面估计会用到。
  2. base memory中[PGSIZE, npages_basemem * PGSIZE)的部分是未分配的。
  3. 然后[IOPHYSMEM, EXTPHYSMEM)作为IO hole 不能被分配
  4. 最后扩展内存中有一部分已经被我们使用了,我们需要通过某些方式知道这一点。

我们可以修改给出的循环如下:

void
page_init(void)
{
   
	size_t i;
	size_t IO_Hole_start = (size_t)IOPHYSMEM / PGSIZE; //the start of IO hole
	size_t IO_Hole_end = (size_t)EXTPHYSMEM / PGSIZE; //the end of IO hole, also the start of the extended memory.
	size_t EXT_Used_end = PADDR(boot_alloc(0)) / PGSIZE; //the end of used extended memory
	//ATTENTION! here the address returned by boot_alloc is virtual memory address which must be translated to physical address since here we are considering physical pages!
	
	//Mark page 0 as used
	pages[0].pp_ref = 1;
	pages[0].pp_link = NULL;

	for (i = 1; i < npages; i++) {
   
	//Mark IO hole and Used Extended Memory as used.
		if (i>= IO_Hole_start && i<EXT_Used_end){
   
			pages[i].pp_ref = 
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值