Lab 2: Memory Management
本实验将为我们自己的内核编写内存管理模块,内存管理模块分为两个部分:第一个部分是内核的物理模块分配器,以便内核分配和释放物理内存,分配器将以4096字节为单位操作,称为页面。第二个部分是虚拟内存管理单元,它将内核和用户软件使用的虚拟地址映射到物理内存中的地址。
Physical Page Management
基础知识补充:bss段是什么。
在采用段式内存管理的架构中(比如intel的80x86系统),bss段(Block Started by Symbol segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域,一般在初始化时bss 段部分将会清零(bss段属于静态内存分配,即程序一开始就将其清零了)。
比如,在C语言程序编译完成之后,已初始化的全局变量保存在.data 段中,未初始化的全局变量保存在.bss 段中。
1.boot_alloc
boot_alloc函数解析,该函数负责物理地址分配,仅在虚拟内存系统创建时使用。
if (!nextfree) {
extern char end[];
nextfree = ROUNDUP((char *) end, PGSIZE);
}
这一段代码中end指向kernel的bss段,应此可以保证虚拟内存的首地址nextfree不会指向内核代码或全局变量。
在boot_alloc函数中接下来要求分配一块空间(pgsize的空间),且要求是对齐的。对齐采用ROUNDUP函数实现,很巧妙ROUNDUP函数可以向上取整除数,正好可以实现内存分配加地址对齐的功能。
result=nextfree;
nextfree=ROUNDUP((char *)nextfree,PGSIZE);
//if out of memory
if((uint32_t)nextfree - KERNBASE > (npages*PGSIZE))
panic("Out of memory!\n");
return result;
到此为止boot_alloc函数补充完成。
2.mem_init
首先初始化一个页表,memset函数负责分配空间并赋0值,详细使用见:
http://c.biancheng.net/view/231.html。
// create initial page directory.
kern_pgdir = (pde_t *) boot_alloc(PGSIZE);
memset(kern_pgdir, 0, PGSIZE);
接下来根据提示,分配npages的页表空间,并给这些空间赋0值。
// 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.
// Your code goes here:
pages=(struct PageInfo*) boot_alloc(npages * sizeof(struct PageInfo));
memset(pages,0,npages * sizeof(struct PageInfo);
接下来我们将调用一个方法page_init(),这个方法也是我们需要完成的方法,而且,在exercise的要求中,mem_init()只用填充到这里,因此到目前为止,mem_init()的填充工作结束。
page_init
BIOS段和extended段不能分配内存,其他位置都可设为free,因此代码如下:
注意PADDR将虚拟地址映射到物理地址。