其他分享
首页 > 其他分享> > MIT6.S081学习总结-lab3:page tables

MIT6.S081学习总结-lab3:page tables

作者:互联网

lab3 主要是页表相关,难度突然提高了好多,遇到了无数个坑,太难了。

打印页表

第一个进程启动时打印页表内容
在这里插入图片描述实现:
kernel/vm.c里添加,递归实现即可
在这里插入图片描述

每个进程一张内核页表

目前xv6的实现里,每个进程只有一张独立的用户地址空间页表,共享一张内核页表,这样的话每次内核不能直接使用用户指针,只能先将其通过用户页表转为物理地址。本节及下一节要做的是使内核可以直接解引用用户指针,就是可以直接通过虚拟地址访问。
本节要做的就是为每个进程复制一个内核页表。

实现

省略了 添加函数到defs.h的步骤,这一节一些实现与下一节相关。

  1. 首先kernel/proc.h里为struct proc添加内核页表
    在这里插入图片描述
  2. kernel/vm.c添加新版本的kvminit用于为每个进程生成内核页表,其中没有映射CLINT,因为用户地址空间为低于PLIC的部分,而CLINT也是低于PLIC的
    在这里插入图片描述之后修改kernel/proc.h,在allocproc里调用上面那个函数新建内核页表,同时将procinit页表映射相关移到allocproc
    在这里插入图片描述
    在这里插入图片描述
  3. scheduler里添加页表切换,每次切换进程时,页表切换到该进程的内核页表
    在这里插入图片描述
  4. 最后释放内存时释放内核页表,这里添加了一个proc_freekpagetable用于释放内核页表。先释放内核页表,再释放用户页表。
    在这里插入图片描述
    这里第221行是因为下一节里需要将用户页表拷贝到内核页表里,因此需要unmap用户地址空间,并不释放物理内存,物理内存在proc_freepagetable里释放。
    在这里插入图片描述

简化 copyin/copyinstr

这一节主要是将每个进程里的用户页表复制到内核页表,这样就可以简化copyin/copyinstr函数,因为可以直接对访问用户指针了。

  1. 替换copyin和copyinstr函数
    在这里插入图片描述在这里插入图片描述
  2. 将进程中用户页表复制到内核页表中
    首先写一个通用函数,在kernel/vm.c
    在这里插入图片描述
    fork里需要调用
    在这里插入图片描述exec里也需要调用,注意调用前需要先释放旧的内核页表里映射的用户页表
    在这里插入图片描述sys_sbrk里内存增加时需要复制到内核页表,内存减少需要解除映射,这里把55行int改为uint64可能会陷入无限循环,出现panic: uvmunmap: walk,某个测试点过不了.
    在这里插入图片描述
    userinit也需要调用,这是第一个进程初始化。不然会开局panic: uvmunmap: walk"
    在这里插入图片描述
  3. 最后在exec里添加 内存大小PLIC限制
    在这里插入图片描述
  4. make grade
    在这里插入图片描述

总结

遇到的比较常见的问题是释放页表时各种 panic, 释放页表一般包括释放页表指向的物理内存和释放页表本身物理内存,uvmunmap用于unmap虚拟内存到物理内存的映射,同时最后一个参数表示是否释放该物理内存,如果没有其它进程页表指向该物理内存才可以释放该物理内存;freewalk用于释放页表本身的物理内存,该页表不能包含叶子,即所有叶子都已经调用了uvmunmap
lab介绍里的提示已经够详细了,还是出现了各种问题,看到panic就想吐了。。有些实在不清楚咋搞,参考了这位大佬的[1].

参考

[1] https://blog.csdn.net/u013577996/article/details/109582932

标签:tables,释放,MIT6,用户,lab3,内核,页表,进程,内存
来源: https://blog.csdn.net/laplacebh/article/details/117933464