OS:lab3实验报告
OS:lab3实验报告 Thinking 3.1 请结合 MOS 中的页目录自映射应用解释代码中 e->env_pgdir[PDX(UVPT)] = PADDR(e->env_pgdir) | PTE_V 的含义。 UVPT是用户地址空间中页表项的起始地址 结合页目录自映射我们知道,只要给定了二级页表项的起始地址,我们就能通过自映射机制计算出页目录的起始虚拟地址 UVPT为二级页表基地址 则页目录基地址为$UVPT + (UVPT»12)*4 = UVPT+UVPT»10$ 映射到页目录的页表项的地址为$UVPT + ((UVPT+UVPT»10)»12)*4 = UVPT + UVPT»10 + UVPT»20$ 该项相对于页目录的index:或者说该项相对于页目录的地址偏移为$UVPT»20$,对应的偏移量为UVPT»22,即为PDX(UVPT) PDX(UVPT)可以得到二级页表起始虚拟地址UVPT的页目录号 e->env_pgdir[PDX(UVPT)]即为指向页目录中指向页目录自身的页目录项 PADDR(e->env_pgdir)得到页目录的物理地址并赋予有效位PTE_V Thinking 3.2 elf_load_seg 以函数指针的形式,接受外部自定义的回调函数 map_page。请你找到与之相关的 data 这一参数在此处的来源,并思考它的作用。没有这个参数可不可以?为什么? data是传入的进程控制块指针 作用:在增加虚拟地址到物理地址的映射时提供当前进程地址空间的页目录基地址pg_dir和asid(load_icode_mapper),所有这个参数是必要的 Thinking 3.3 结合 elf_load_seg 的参数和实现,考虑该函数需要处理哪些页面加载的情况 elf_load_seg函数的实现(elfloader.c) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 int elf_load_seg(Elf32_Phdr *ph, const void *bin, elf_mapper_t map_page, void *data) { u_long va = ph->p_vaddr; size_t bin_size = ph->p_filesz; size_t sgsize = ph->p_memsz; u_int perm = PTE_V; if (ph->p_flags & PF_W) { perm |= PTE_D; } int r; size_t i; u_long offset = va - ROUNDDOWN(va, PAGE_SIZE); if (offset != 0) { if ((r = map_page(data, va, offset, perm, bin, MIN(bin_size, PAGE_SIZE - offset))) != 0) { return r; } } /* Step 1: load all content of bin into memory. */ for (i = offset ? MIN(bin_size, PAGE_SIZE - offset) : 0; i < bin_size; i += PAGE_SIZE) { if ((r = map_page(data, va + i, 0, perm, bin + i, MIN(bin_size - i, PAGE_SIZE))) != 0) { return r; } } /* Step 2: alloc pages to reach `sgsize` when `bin_size` < `sgsize`. */ while (i < sgsize) { if ((r = map_page(data, va + i, 0, perm, NULL, MIN(sgsize - i, PAGE_SIZE))) != 0) { return r; } i += PAGE_SIZE; } return 0; } ...