1、boot_alloc(),分配n字节的物理内存,返回内核虚拟地址。这只是一个简单的物理内存分配程序,尽在虚拟内存的设置中才用到,page_alloc()是真正的分配函数:
=======================================自己的代码===================================
static void*
boot_alloc(uint32_t n, uint32_t align)
{
extern char end[];
void *v;
// Initialize boot_freemem if this is the first time.
// 'end' is a magic symbol automatically generated by the linker,
// which points to the end of the kernel's bss segment -
// i.e., the first virtual address that the linker
// did _not_ assign to any kernel code or global variables.
if (boot_freemem == 0)
boot_freemem = end;
//Step1:
boot_freemem = ROUNDUP(boot_freemem, align);
//setp2:
v = boot_freemem;
//setp 3:
boot_freemem += ROUNDUP(n, align);
assert(PADDR(boot_freemem) <= maxpa);
//setp 4;
return v;
}
============================================end==================================
2、Page_init(),初始化页及空的内存链表。在此以后,仅仅通过page_free_list用来分配与释放物理内存:
=======================================自己的代码===================================
void
page_init(void)
{
//mark page 0 in use for IDT and BIOS use
pages[0].pp_ref = 1;
////mark rest of pages free by setting their num refs = 0 and
////appending them to the page_free_list
//init the list
LIST_INIT(&page_free_list);
//add to free list pages from [PGSIZE, IOPHYSMEM)
//determine idx of page up to IOPHYSMEM
int iophysmem_idx = IOPHYSMEM / PGSIZE;
int i;
for (i = 1; i < iophysmem_idx; i++) {
pages[i].pp_ref = 0;
//add page to head of list to build page_free_list
LIST_INSERT_HEAD(&page_free_list, &pages[i], pp_link);
}
//mark IO hole [IOPHYSMEM, EXTPHYSMEM) so it can't be allocated
int extphysmem_idx = EXTPHYSMEM / PGSIZE;
for(i = iophysmem_idx; i < extphysmem_idx; i++) {
pages[i].pp_ref = 1;
}
//extend memory
//npage is amount of physical pages in memory set by i386
//kernel lives from [EXTPHYSMEM, boot_freemem)
//add to free_list pages from [boot_freemem, npage * PGSIZE)
int boot_freemem_idx = ROUNDUP( PADDR( boot_freemem ), PGSIZE) / PGSIZE;
for(i = boot_freemem_idx; i < npage; i++) {
pages[i].pp_ref = 0;
LIST_INSERT_HEAD(&page_free_list, &pages[i], pp_link);
}
}
============================================end==================================
3、page_alloc(),分配一个物理页面。但并不将其内容初始化为0。
=======================================自己的代码===================================
int
page_alloc(struct Page **pp_store)
{
// Fill this function in
// *pp_store指向新分配的页面
//
// 返回值:
// 成功:0
// 其他:-E_NO_MEM
//check if there are no free pages
if LIST_EMPTY(&page_free_list) return -E_NO_MEM;
//store ptr to page
*pp_store = LIST_FIRST(&page_free_list);
//remove page from list
LIST_REMOVE(*pp_store, pp_link);
//init the new page struct
page_initpp(*pp_store);
//told not to inc ref count, so don't
//return success
return 0;
}
============================================end==================================
4、page_free(),向空页表的链表中加入一个页,当且仅当pp->pp_ref为0时才能调用该函数
=======================================自己的代码===================================
void
page_free(struct Page *pp)
{
// Fill this function in
assert(pp->pp_ref==0);
LIST_INSERT_HEAD(&page_free_list, pp, pp_link);
}
============================================end==================================
5、在i386_vm_init()函数中,将check_page_alloc()之前的代码补充完整(仅列出自己填写的部分):
=======================================自己的代码===================================
void
i386_vm_init(void)
{
......
//////////////////////////////////////////////////////////////////////
// Make 'pages' point to an array of size 'npage' of 'struct Page'.
// The kernel uses this structure to keep track of physical pages;
// 'npage' equals the number of physical pages in memory. User-level
// programs will get read-only access to the array as well.
// You must allocate the array yourself.
// Your code goes here:
n = ROUNDUP(npage*sizeof(struct Page), PGSIZE);
pages = (struct Page *)boot_alloc(n, PGSIZE);
......
}
============================================end==================================