1. 程式人生 > 其它 >Copy on Write實現

Copy on Write實現

xv6中並沒有實現這個部分,我自己實現的COW程式碼沒有儲存,因此借用了別人的程式碼,主要是瞭解實現方法。

COW(copy on write)指fork複製子程序時,並不直接複製父程序的記憶體內容至子程序中(因為開銷很大),而是將這些記憶體的一個特殊COW標誌置1。因此,子程序讀記憶體時,實際上是讀的父程序的記憶體。當子程序或者父程序需要寫記憶體時,作業系統將使用缺頁中斷將涉及的記憶體頁表單獨複製。即將記憶體複製的過程延後,並且僅處理使用到的記憶體部分,可以極大的節約資源消耗。

  1. 首先建立int refNum[32768],用來記錄每個物理頁的實際關聯數,即子程序複製父程序頁時,只是對refNum中對應的物理頁做+1操作
  1. 在頁表項中新增PTE_COW標誌位。

  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狀態,需要將目標頁的內容複製到新的頁中。