从文件kern/kernel.ld的内容可知,内核将被加载到地址0xF0100000处。
函数i386_init()中调用i386_detect_memory(), 得到内存的大小。
函数i386_vm_init()中,通过函数boot_alloc()分配页目录pgdir. 可知内核中分配的内存地址将在KERNBASE(0xf0000000)以上。从boot_alloc的实现中有这样一句:boot_freemem = end; 而end定义于ern/kernel.ld中也可知道这一点。
类似的,数组pages的地址也在KERNBASE以上。数组pages的成员为所有的物理内存页面,其索引为0~npage。而page_free_list则是该数组中所有pp_ref值为0的元素的链表。而KERNBASE以上可用的内存只能通过pages使用,大小为i386_detect_memory()中获得的值,最多不超过256M。
页目录和页表其自身地址均在KADDR内,但二者中各项内容所含的地址值则都位于0~256M的物理地址空间内。
而pages数组各元素只定义了一个成员pp_ref, 那么,这些元素是怎么和物理内存一一对应的呢?这是通过pages的索引和物理内存从0M开始的关系来联系起来的。pages[X]对应物理内存X*4K~(X+1)*4K. 具体实现是通过kern/pmap.h中的四个函数实现的:
static inline ppn_t
page2ppn(struct Page *pp)
{
return pp - pages;
}
static inline physaddr_t
page2pa(struct Page *pp)
{
return page2ppn(pp) << PGSHIFT;
}
static inline struct Page*
pa2page(physaddr_t pa)
{
if (PPN(pa) >= npage)
panic("pa2page called with invalid pa");
return &pages[PPN(pa)];
}
static inline void*
page2kva(struct Page *pp)
{
return KADDR(page2pa(pp));
}
阅读(2306) | 评论(1) | 转发(0) |