最近做lazy lab做的有点头大,突然发现是自己遗漏了一些内容,即lec5,6,因为刚开始看的时候很多看不懂,就跑去看书了,后来就一直没有回来看lecture
所以为了提高效率,应该快速的把书看一遍,然后回来看lecture,再带着问题去看书看代码
code walk through
kvminit
void kvminit()
{
// 确定64bit的一级目录地址
kernel_pagetable = (pagetable_t) kalloc();
memset(kernel_pagetable, 0, PGSIZE);
// 一对一的IO映射 1 page
kvmmap(UART0, UART0, PGSIZE, PTE_R | PTE_W);
kvmmap(VIRTION(0), VIRTION(0), PGSIZE, PTE_R | PTE_W);
kvmmap(VIRTION(1), VIRTION(1), PGSIZE, PTE_R | PTE_W);
// CLINT 16 pages
kvmmap(CLINT, CLINT, 0x10000, PTE_R | PTE_W);
// PLIC 1024 pages
kvmmap(PLIC, PLIC, 0x400000, PTE_R | PTE_W);
// memlayout.h
// #define KERNBASE 0x80000000L
// #define PHYSTOP (KERNBASE + 128*1024*1024) 所以内核共映射了128M的内存
// #define TRAMPOLINE (MAXVA - PGSIZE)
// etext 在kernel.ld中,编译器根据代码量确定的对齐地址,ALGIN(0x1000),不懂意思
kvmmap(KERNBASE, KERNBASE, (uint64)etext-KERNBASE, PTE_R | PTE_X);
// 映射数据段和空闲内存
kvmmap((uint64)etext, (uint64)etext, PHYSTOP-(uint64)etext, PTE_R | PTE_W);
// 只有trampoline不是直接映射,实际的位置已经出现在代码段了,KERNBASE~etext。该段代码二次映射
kvmmap(TRAMPOLINE, (uint64)trampoline, PGSIZE, PTE_R | PTE_X);
}
kvmmap
直接调用了mappages(pagetable,va,size,pa,permission) , 而mappages是建立va~va+sz的pte:通过kalloc得到物理地址,然后设置pte
int
mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm)
{
uint64 a, last;
pte_t *pte;
a = PGROUNDDOWN(va);
last = PGROUNDDOWN(va + size - 1);
for(;;){
if((pte = walk(pagetable, a, 1)) == 0)
return -1;
if(*pte & PTE_V)
panic("remap");
*pte = PA2PTE(pa) | perm | PTE_V;
if(a == last)
break;
a

本文详细介绍了xv6操作系统中虚拟内存的管理,包括kvminit、kvmmap等函数的实现,以及如何分配和映射用户内存空间。在procinit中为进程分配内核栈,allocproc和fork中创建和复制页表,uvmcopy用于复制用户内存,exec则负责加载ELF文件到进程地址空间。此外,文章还讨论了exec系统调用的执行流程及其如何改变进程的执行路径。
最低0.47元/天 解锁文章
1625

被折叠的 条评论
为什么被折叠?



