Jos-lab3 (Exercise 1 & 2)

本文详细介绍如何在Xv6操作系统中实现内存管理的关键步骤,包括环境设置、虚拟内存分配及映射等。通过具体代码示例展示了如何为用户进程分配和初始化页目录,以及如何加载ELF程序并为其分配内存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Exercise 1.Modify mem_init() in kern/pmap.cto allocate and map the envs array.This array consists o fexactly NENV instances of the Env structure allocated much like how you allocated the pages array.Also like the pages array, the memory backing envs should also be mapped user read-only at UENVS (defined in inc/memlayout.h) so user processes can read from this array.

You should run your code and make sure check_kern_pgdir() succeeds.

Answer:

        // Make 'envs' point to an array of size 'NENV' of 'struct Env'.

        // LAB 3: Your code here.
-
+       envs = (struct Env *)boot_alloc(NENV * sizeof(struct Env));
+       memset(pages, 0, NENV * sizeof(struct Env));
        //////////////////////////////////////////////////////////////////////
        // Now that we've allocated the initial kernel data structures, we set
        // up the list of free physical pages. Once we've done so, all further
@@ -203,7 +204,9 @@ mem_init(void)
        //    - the new image at UENVS  -- kernel R, user R
        //    - envs itself -- kernel RW, user NONE
        // LAB 3: Your code here.
-
+       boot_map_region(kern_pgdir, UENVS,
+                       ROUNDUP(NENV*sizeof(struct Env), PGSIZE),
+                       PADDR(envs), PTE_U);

Exercise 2.In the file env.c,finish coding the following functions:

env_init()
Initialize all of the Env structures in the envs array and add them to the env_free_list.Also calls env_init_percpu, which configures the segmentation hardware with separate segments for privilege level 0 (kernel) and privilege level 3 (user).
122         env_free_list = envs;
123         struct Env *iter = env_free_list;
124         while (i < NENV) {
125                 envs[i].env_id = 0;
126                 envs[i].env_status = ENV_FREE;
127                 i++;
128                 iter->env_link = envs + i;
129         }Q: envs在mem_init()里用boot_map_region()已经申请过空间了,就物理空间上应该是紧挨着pages?

env_setup_vm()
Allocate a page directory for a new environmentand initialize the kernel portionof the new environment's address space.

198         p->pp_ref++;
199         e->env_pgdir = page2kva(p);
200         memmove(e->env_pgdir,kern_pgdir,PGSIZE);
201         memset(e->env_pgdir,0,PDX(UTOP)*sizeof(pde_t));

原来以为是做映射,其实这边每个enviroment都需要有一个pgdir,让每个用户环境都能映射到4GB的空间。kern_pgdir已经映射到4GB空间,而对于UTOP以上的空间,所有的user enviroment都是和kernel一样的映射,因此可以直接copy过来用。

region_alloc()
Allocates and maps physical memory for an environment

284         uint32_t ua,la;
285         ua = (uint32_t)ROUNDUP(va+len, PGSIZE);
286         la = (uint32_t)ROUNDDOWN(va, PGSIZE);
287         uint32_t size = 0;
288         struct Page *p = NULL;
289         for(size = 0;size < (ua - la);size += PGSIZE) {
290                 if (!(p = page_alloc(ALLOC_ZERO)))
291                         panic("page allocation failed!\n");
292 // Jacky: Original I thought should use boot_map_region to map, but     actually it's only a static mapping, should use page_insert
293 //              boot_map_region(e->env_pgdir, va+size, PGSIZE,
294 //                              page2pa(p), PTE_W|PTE_U);
295                 page_insert(e->env_pgdir, p, va+size, PTE_W|PTE_U);
296         }

load_icode()
You will need to parse an ELF binary image,much like the boot loader already does,and load its contents into the user address spaceof a new environment.
358         // LAB 3: Jacky 14020.
359         struct Elf *elf = (struct Elf *)binary;
360         struct Proghdr *ph, *eph;
361         if(elf->e_magic != ELF_MAGIC) {
362                 cprintf("%s() It's not an ELF file!\n",__func__);
363                 return;
364         }
365         // Mistake 1: Almost miss this one, it's changing the address space from k    ernel to e enviroment;
366         lcr3((uint32_t)e->env_pgdir);
367         ph = (struct Proghdr *) ((uint8_t *)elf + elf->e_phoff);
368         eph = ph + elf->e_phnum;
369         for (;ph<eph;ph++) {
370                 if (ph->p_type != ELF_PROG_LOAD)
371                         continue;
372                 region_alloc(e,(void *)ph->p_va,ph->p_memsz);
373                 memmove((void *)ph->p_va, (uint8_t *)elf + ph->p_offset, ph->p_fil    esz);
374                 memset((void *)(ph->p_va + ph->p_filesz), 0, ph->p_memsz - ph->p_f    ilesz);
375         }
376         // Mistake 2: set the enviroment's entry point
377         e->env_tf.tf_eip = elf->e_entry;
378
379         // Now map one page for the program's initial stack
380         // at virtual address USTACKTOP - PGSIZE.
381
382         // LAB 3: Jacky 140120
383         region_alloc(e, (void *)(USTACKTOP-PGSIZE), PGSIZE);

env_create()
Allocate an environment with env_allocand call load_icode load an ELF binary into it.
395 {
396         // LAB 3: Jacky140120
397         struct Env* e;
398         int failno = env_alloc(&e, 0);
399         if (failno < 0) {
400                 cprintf("%s(0x%x, %d, %d) failed, fail code = %d!\n",__func__, bin    ary, size, type);
401                 return;
402         }
403         load_icode(*e, binary, size)
404         e->env_type = type;
405 }      

env_run()
Start a given environment running in user mode.
521         if (curenv) {
522                 if(curenv->env_status == ENV_RUNNING)
523                         curenv->env_status = ENV_RUNNABLE;
524         }
525         curenv = e;
526         curenv->env_status = ENV_RUNNING;
527         curenv->env_runs++;
528         lcr3(PADDR(curenv->env_pgdir));
529
530         env_pop_tf(&curenv->env_tf);
531         panic("env_run not yet implemented");

As you write these functions,you might find the new cprintf verb %euseful -- it prints a description corresponding to an error code.For example,

	r = -E_NO_MEM;
	panic("env_alloc: %e", r);

will panic with the message "env_alloc: out of memory".



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值