MIT 6.828 学习笔记5 Lab3实验报告

Lab3 实验报告

Exercise 1

  • Modify mem_init() in kern/pmap.c to allocate and map the envs array.
// mem_int()
// 第一处
envs = (struct Env *) boot_alloc(NENV * sizeof(struct Env));
memset(pages, 0, NENV * sizeof(struct Env));

// 第二处
boot_map_region(kern_pgdir, UENVS, PTSIZE, PADDR(envs), PTE_U | PTE_P);

这里仿照上一个实验可以比较轻松的写出来,注意,由于内核已用内存多出了 NENV 这一段,所以还需要修改 page_init 函数内的上限,参照 LAB 2 实验报告的代码,修改如下

// page_init()
size_t right_i = PGNUM(PADDR(envs + NENV));

Exercise 2

  • In the file env.c, finish coding the following functions.
// env_init()
env_free_list = envs;
struct Env *pre = envs;
for (int i = 1; i != NENV; ++i) {
    pre -> env_link = envs + i;
    pre = envs + i;
}

这里是初始化 envs 数组,然后插入到空闲链表中,由注释可知,需要确保分配 env 的时候是从 env[0] 开始分配的,也就是使用尾接法建链表,这和之前的 pages 不同

// env_setup_vm()
p->pp_ref++;
e->env_pgdir = page2kva(p);
memcpy(e->env_pgdir, kern_pgdir, PGSIZE);

初始化用户地址空间中内核部分的虚拟内存并设置一级页表,可以将之前的 kern_pgdir 复制过去

// region_alloc()
uintptr_t low = ROUNDDOWN((uintptr_t) va, PGSIZE);
uintptr_t high = ROUNDUP((uintptr_t) va + len, PGSIZE);
if (high > UTOP) {
    panic("allocation fails");
}
while (low < high) {
    struct PageInfo *pp = page_alloc(ALLOC_ZERO);
    if (pp == NULL) {
        panic("allocation falis");
    }
    pp->pp_ref++;
    int r = page_insert(e->env_pgdir, pp, (void *) low, PTE_P | PTE_U | PTE_W);
    if (r != 0) {
        panic("region_alloc: %e", r);       
    }
    low += PGSIZE;
}

env 分配物理内存,接着映射到虚拟内存,注意需要对齐以及考虑边界情况

// load_icode()
// 第一处
struct Elf *elf = (struct Elf *) binary;
struct Proghdr *ph = (struct Proghdr *) (binary + elf->e_phoff);
struct Proghdr *eph = ph + elf->e_phnum;
lcr3(PADDR(e->env_pgdir));
while (ph < eph) {
    if (ph->p_type == ELF_PROG_LOAD) {
        region_alloc(e, (void *) ph->p_va, ph->p_memsz);
        memcpy((void *) ph->p_va, binary + ph->p_offset, ph->p_filesz);
    }
    ph++;
}
lcr3(PADDR(kern_pgdir));
e->env_tf.tf_eip = elf->e_entry;

// 第二处
region_alloc(e, (void *) (USTACKTOP - PGSIZE), PGSIZE);

elf 二进制文件读入用户地址空间中,仿照 bootloadermain.c 的做法,需要了解 elf 文件的结构,这个之前学习过,需要注意的是,为了读入用户地址空间,需要切换到用户的页表,还有记得设置 eip 指向入口处

// env_create()
struct Env *e;
int r = env_alloc(&e, 0);
if (r < 0) {
    panic("env_alloc: %e", r);
}
load_icode(e, binary);
e->env_type = type;

利用之前的函数创建 env ,对于 parent_id 由于分配页面的时候,把页面都清 0 了,所以这里不显式设置也

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值