MIT6.828 JOS系统 lab2

本文详细介绍了MIT6.828 LAB2的内容,重点讲解了系统的分页过程、虚拟地址到物理地址的转换,以及如何管理内存。讨论了boot_alloc()、mem_init()、page_init()、page_alloc()和page_free()等关键函数的实现。此外,还详细阐述了虚拟内存的二级分页机制,包括pgdir_walk()、boot_map_region()、page_lookup()、page_remove()和page_insert()等功能。最后分析了操作系统对内核地址空间的保护以及内存管理的开销。
摘要由CSDN通过智能技术生成

MIT6.828 LAB2:http://pdos.csail.mit.edu/6.828/2014/labs/lab2/

LAB2里面主要讲的是系统的分页过程,还有就是简单的虚拟地址到物理地址的过程。关于系统分页,在MIT6.828 虚拟地址转化为物理地址——二级分页http://blog.csdn.net/fang92/article/details/47320747中有讲。

下面主要是lab2的几个exercise的解题过程。

1.第一个boot_alloc()函数:

static void *
boot_alloc(uint32_t n)
{
	static char *nextfree;	// virtual address of next byte of free memory
	char *result;

	if (!nextfree) {
		extern char end[];<span style="white-space:pre">	</span>//end points to the end of the kernel's bss segment:
		nextfree = ROUNDUP((char *) end, PGSIZE);
	}
	if(n==0)
		return nextfree;
	result = nextfree;
	nextfree += n;
	nextfree = ROUNDUP( (char*)nextfree, PGSIZE);
	return result;
}
boot_alloc(unit32_t n)主要是申请n个字节的地址空间,返回申请空间的首地址。如果n是0,则返回nextfree(未分配空间的首地址)。其中,分配的地址是页对齐的,即4K对齐。

这个函数,巧妙应用了未初始化的全局变量和静态变量会被自动初始化为0这个特性。函数以首先定义静态局部变量nextfree,它指向空闲内存空间的首地址。由于未初始化,所以变量自动初始化为0,所以首次调用boot_alloc()函数的时候,nextfree的值是0,会执行下面的语句:

if (!nextfree) {
		//end points to the end of the kernel's bss segment
		nextfree = ROUNDUP((char *) end, PGSIZE);
	}


end指向的是bss段的末尾,通过调用objdump -h kernel 可以看程序的各个段的信息。

上面的图片可以看出,在整个程序里面,.bss段的位置是最下面的,注意.comment段是一些程序的注释信息,是不进内存的。所以end未初始化的全局变量,在.bss段中。所以end是指向的是整个内存的最后一个地址。(.bss段到底是怎么回事)。

接下来的ROUNDUP就是一个宏定义,用来4K对齐的,最后会返回一个地址,指向end的下一个空闲页的首地址。

所以在系统第一次调用boot_alloc()这个函数的时候,首先nextfree会被指向第一个空闲页的首地址。接下来,根据输入的n,来分配地址。如果n=0,则返回nextfree,否则分配n字节的地址,返回分配地址的首地址。注意,整个过程中,需要4K对齐。

2.mem_init()函数

这个函数只需要补充一部分就可以了。主要是要为struct PageInfo的结构体的指针pages申请一定的地址空间。首先来看struct PageInfo的定义:

struct PageInfo 
	{ 	//Next page on the free list.
		struct PageInfo *pp_link;
		uint16_t pp_ref;
		}
这个结构体,主要是用来保存内存中的所有物理页面的信息的。每一个PageInfo对应一个物理页面。

pageInfo主要有两个变量:

pp_link表示下一个空闲页,如果pp_link=0,则表示这个页面被分配了,否则,这个页面未被分配,是空闲页面。

pp_ref表示页面被引用数,如果为0,表示是空闲页。(这个变量类似于智能指针中指针的引用计数)。

补充的代码比较简单,就是位pages申请足够的空间(npages的页面),来存放这些结构体,并且用memset来初始化:

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


关于pages:

pages是用来管理物理内存页的一个结构体。首先,pages是整个系统物理内存的第0页,pages的值是一个虚拟地址。由于结构体是连续的,所以通过pages[i]-pages可以得到页的编号i,在通过i<<12就可以得到pages[i]所对应的页的物理内存,由于实现系统的物理内存和虚拟内存的转换比较简单,虚拟内存=物理内存+ 0xF0000000.所以通过pages这个结构体,在知道具体的物理页时,就可以很容易得到物理页对应的物理地址和虚拟地址,如图。

3.page_init()

page_init()函数主要就是结构体pages的初始化,就是在系统刚刚开始运行时,对物理内存分配进行初始化操作,按照上面的提示一步一步写就可以了,比较简单。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值