Ucore lab2

lab2

Page数据结构是如何跟实际物理页联系起来的呢?
struct Page {
int ref; // page frame’s reference counter
uint32_t flags; // array of flags that describe the status of the page frame
unsigned int property; // the num of free block, used in first fit pm manager
list_entry_t page_link; // free list link
};
简单来说,就是用一个Page对象中page_link的地址,减去page_link在Page结构中的偏移量,找到相应的Page对象的地址,然后强转成Page对象。
st_entry_t通用双向循环链表中仅保存了某特定数据结构中链表节点成员变量的地址,那么如何通过这个链表节点成员变量访问到它的所有者(即某特定数据结构的变量)呢?Linux为此提供了针对数据结构XXX的le2XXX(le, member)的宏,其中le,即list entry的简称,是指向数据结构XXX中list_entry_t成员变量的指针,也就是存储在双向循环链表中的节点地址值, member则是XXX数据类型中包含的链表节点的成员变量。例如,我们要遍历访问空闲块链表中所有节点所在的基于Page数据结构的变量,则可以采用如下编程方式(基于lab2/kern/mm/default_pmm.c):
//free_area是空闲块管理结构,free_area.free_list是空闲块链表头
free_area_t free_area;
list_entry_t * le = &free_area.free_list; //le是空闲块链表头指针
while((le=list_next(le)) != &free_area.free_list) { //从第一个节点开始遍历
struct Page *p = le2page(le, page_link); //获取节点所在基于Page数据结构的变量
……
}

ucore中采用的方法是将struct Page按照他们所管辖的物理页面的地址大小进行连续储存, 所以可以使用page2pa宏通过对page结构提首地址进行移位操作获得对应地址, 详情可见mm/pmm.h, 其中pages可以认为是存储所有struct Page的首地址.
static inline ppn_t
page2ppn(struct Page *page) {
return page - pages;
}

static inline uintptr_t
page2pa(struct Page *page) {
return page2ppn(page) << PGSHIFT;
}

memlayout.h 定义的 KERNEL BASE 是 #define KERNBASE 0xC0000000 。
ucore kernel的虚拟内核空间的起始地址为0xC0000000,

而 tools/kernel.ld (ld链接工具的配置文件),指出了

SECTIONS {
/* Load the kernel at this address: “.” means the current address */
. = 0xC0100000; <—-说明了编译出的kernel执行文件的虚拟内核的起始地址为0xC0100000,这个地址就是 kern_entry 函数(位于kern/init/entry.S)的起始地址。

pte2page只是pa2page的一个封装而已,用哪一个意义上都是一样的。

最先匹配是说空闲分区列表按照地址顺序排列,可是lab2中的answer好像是每次把free后把空闲的直接加到列表头了

get_pte中, 在页表不存在((pgdir[pdx] & PTE_P) == 0)的时候需要分配空间放置页表并重新填写页目录项:
0xC0000000为KERNBASE, 为虚拟地址空间中的内核基址, 在ucore中内核地址仅做一个平移映射, 所以物理地址加0xC0000000就是其虚拟地址, 至于0xC0000000这个值是人为设定的, 没有特别原因, 不同操作系统可能有不同的.
虚拟地址到物理地址的转换是由硬件完成的.

lab2 /mm/mmu.h

#define PTE_P 0x001 // Present
#define PTE_W 0x002 // Writeable
#define PTE_U 0x004 // User
#define PTE_PWT 0x008 // Write-Through
#define PTE_PCD 0x010 // Cache-Disable
#define PTE_A 0x020 // Accessed
#define PTE_D 0x040 // Dirty
#define PTE_PS 0x080 // Page Size
#define PTE_MBZ 0x180 // Bits must be zero
#define PTE_AVAIL 0xE00 // Available for software use

PTE_PS是对pde说的,如果pde的PTE_PS位为1,那么pde中所存的就不是下一级页表,而是一张4M页的起始地址;也就是说,这是页的粒度不是4K,而是4M

PG_reserved=1的页属于:已经被kernel code或一些全局变量占用了的内存,或者是不能用于一般读写的内存。
PG_reserved=0的页是可以用来alloc/free的内存。reserved的页不能被分配了,default_pmm就是一个pm_manager,用于管理以页为单位的空闲内存.

你可能感兴趣的:(Ucore lab2)