Lab5 Copy-on-Write
COW机制介绍
COW的机制其实非常简单,核心思想还是将内存的分配推迟:在fork()
的时候只是将子进程的虚拟页映射到父进程的物理内存上;当之后发生了实际的写内存操作引发page fault
后,再进行实际的内存分配。
COW实现
尽管COW的机制非常简单,实现起来也看似简单,但是非常易错,且调试难度也比较大(多核并发)
具体代码见:cow lab
实现过程基本上参考手册的那几步就行:
1、修改 uvmcopy()
函数,将parent
的物理页映射到child
的页表中,而不是分配新的物理页,并且清空PTE_W
标志,设置cow page
的标识。
1 |
|
2、在usertrap()
中识别page fault
,并进行相应的处理。
1 |
|
3、对物理页设置引用计数机制
这一部分应该是最难的一块,需要考虑并发加锁。
1 |
|
4、修改copyout
,机制和处理page fault
一样
1 |
|
错误汇总
1、报错 remap
原因是在建立新的映射之前,要先将原来的映射取消掉;
2、scause = 2 非法指令
思考排错的过程:
初步猜测是:在用户空间使用内核指令?
根据backtrace出错的位置:在用户空间是
cowtest
中的simpletest
,在wait(0)
后面的r_scause()
引发了错误
可能是地址空间出现错误!需要严格检查地址是否越界等!
但是 该错误一直没有得到解决
经过长时间的debug,发现出现错误的原因是没有正确地实现引用计数机制,出现了并发的错误。本来在实现的过程中,是想实现一点测试一点的,以为实现好了基本的功能应该能跑过简单测试,所以在排错的时候一直没有考虑是引用计数的问题!
3、减少引用计数的位置
在修改引用计数机制的时候,我是希望将引用的更新作为一个函数,然后当更新后的引用为0
的时候再调用kfree
释放物理内存,这个时候就会出现一个问题:这样实现相当于在kfree
的前面加了一层引用更新函数,在cow page
的相关实现中是可以正确调度内存的释放,但是系统的其他地方会有直接调用kfree的情况,就会导致
即使该内存页的引用不为0
该内存页还是被释放了的情况,所以减少引用计数的位置应该在kfree
中。