其他分享
首页 > 其他分享> > MIT6.S081学习总结-lab6:Copy-On-Write Fork

MIT6.S081学习总结-lab6:Copy-On-Write Fork

作者:互联网

lab6 也是虚拟内存的一种应用,主要实现fork时的写时复制copy-on-write功能。

问题

xv6中的fork()系统调用将所有父进程的用户空间内存复制到子进程中。如果父进程用户空间很大,复制可能需要很长时间。更糟糕的是,这种复制工作经常被浪费;例如,子进程中的fork()后跟exec()将导致子进程丢弃复制的内存,可能根本就没有使用复制来的很大一部分内存。另一方面,如果父类和子类都使用一个页面,而其中一方或双方都编写该页面,则确实需要一个副本。

解决方法

写时拷贝(COW) fork()的目标是推迟为子进程分配和复制物理内存页,直到实际需要复制时才进行分配和复制。

COW fork()仅为子进程创建一个分页表,用户内存的pte指向父进程的物理页。COW fork()将父级和子级的所有用户pte标记为不可写。当任何一个进程尝试写其中一个COW页面时,CPU将出现页面错误。内核页错误处理程序检测到这种情况,为出错进程分配一个物理内存页,将原始页复制到新页,并在出错进程中修改相关的PTE以引用新页,这一次PTE标记为可写。当页面错误处理程序返回时,用户进程就能够写入该页面了。

COW fork()使得释放用户内存的物理页变得更为麻烦。一个给定的物理页可能被多个进程的页表引用,并且只有当最后一个引用消失时才应该被释放。

Implement copy-on write

实现:

在kalloc.c中增加物理内存引用计数
在这里插入图片描述
分配内存时初始化引用计数为1
在这里插入图片描述

释放内存时查看引用计数是否为0,注意kinit会调用一次kfree
在这里插入图片描述
获取和增加引用计数的函数,减少的话可以直接调用kfree。对引用计数全程不加锁,这个lab也可以通过tests
在这里插入图片描述

增加COW标志位,可以使用预留的第8位或者第9位
在这里插入图片描述

vm.c 里uvmcopy函数修改为只将子进程页表映射到父进程的物理地址,去掉写标志位,增加COW标志位,增加物理内存引用计数
在这里插入图片描述

trap.c里usertrap增加页面错误的处理,需判断是否是COW
在这里插入图片描述
vm.c里加了个walkpte函数,就是修改了walkaddr函数返回值,这个函数返回pte
在这里插入图片描述

最后copyout也要增加页面错误处理,因为copyout是在内核中调用的,缺页不会进入usertrap。
在这里插入图片描述
在这里插入图片描述

总结

COW在实现上主要问题体现在 物理页面的引用计数实现以及判断是否为cow页面 这两个方面。理清了思路就比较好理解,之后就是一些实现细节方面,最容易出现usertrap错误,这时可以根据sepc查看在哪个地方出现错误然后解决。

标签:Fork,fork,COW,MIT6,引用,Write,内存,进程,页面
来源: https://blog.csdn.net/laplacebh/article/details/118358462