首页 > 技术文章 > Copy on Write实现

zhushoucheng 2021-11-19 16:57 原文

xv6中并没有实现这个部分,我自己实现的COW代码没有保存,因此借用了别人的代码,主要是了解实现方法。

COW(copy on write)指fork复制子进程时,并不直接复制父进程的内存内容至子进程中(因为开销很大),而是将这些内存的一个特殊COW标志置1。因此,子进程读内存时,实际上是读的父进程的内存。当子进程或者父进程需要写内存时,操作系统将使用缺页中断将涉及的内存页表单独复制。即将内存复制的过程延后,并且仅处理使用到的内存部分,可以极大的节约资源消耗。

  1. 首先创建int refNum[32768],用来记录每个物理页的实际关联数,即子进程复制父进程页时,只是对refNum中对应的物理页做+1操作
在这里插入图片描述
  1. 在页表项中新增PTE_COW标志位。

    在这里插入图片描述

img
  1. 修改fork函数中的uvmcopy()函数(该函数用于复制父进程内存到子进程),不复制内存,而改为将物理页的对应refNum+1
在这里插入图片描述

下面是原代码,对比一下即可发现不再调用memmove函数了

    pa = PTE2PA(*pte);
    flags = PTE_FLAGS(*pte);
    if((mem = kalloc()) == 0)
      goto err;
    memmove(mem, (char*)pa, PGSIZE);
    if(mappages(new, i, PGSIZE, (uint64)mem, flags) != 0){
      kfree(mem);
      goto err;
    }
在这里插入图片描述
  1. 修改中断处理函数usertrap。缺页中断会使scause寄存器置为13,可以借此判断中断类型。

    缺页中断的目标地址存储在stval寄存器中,使用walk函数通过页表获得该虚拟地址对应的物理页的pte

    判断pte的refNum关联数,如果等于2,说明该页不再处于COW状态,将COW标志去除,write标志打开,表明可以对该内存页进行写操作

    如果大于2,说明该页处于COW状态,需要将目标页的内容复制到新的页中。

在这里插入图片描述

推荐阅读