Linux

關於核心中copy_pte_range()的兩個問題

  • March 22, 2019

我一直在試圖了解它是如何fork()工作的,最終到達了copy_pte_range(). 大多數功能是可以理解的,但很少有非常值得懷疑的。

核心:4.14.84

static int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
          pmd_t *dst_pmd, pmd_t *src_pmd, struct vm_area_struct *vma,
          unsigned long addr, unsigned long end)
{
   pte_t *orig_src_pte, *orig_dst_pte;
   pte_t *src_pte, *dst_pte;
   spinlock_t *src_ptl, *dst_ptl;
   int progress = 0;
   int rss[NR_MM_COUNTERS];
   swp_entry_t entry = (swp_entry_t){0};

again:
   init_rss_vec(rss);

   dst_pte = pte_alloc_map_lock(dst_mm, dst_pmd, addr, &dst_ptl);
   if (!dst_pte)
       return -ENOMEM;
   src_pte = pte_offset_map(src_pmd, addr);
   src_ptl = pte_lockptr(src_mm, src_pmd);
   spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING);
   orig_src_pte = src_pte;
   orig_dst_pte = dst_pte;
   arch_enter_lazy_mmu_mode();

   do {
       /*
        * We are holding two locks at this point - either of them
        * could generate latencies in another task on another CPU.
        */
       if (progress >= 32) {
           progress = 0;
           if (need_resched() ||
               spin_needbreak(src_ptl) || spin_needbreak(dst_ptl))
               break;
       }
       if (pte_none(*src_pte)) {
           progress++;
           continue;
       }
       entry.val = copy_one_pte(dst_mm, src_mm, dst_pte, src_pte,
                           vma, addr, rss);
       if (entry.val)
           break;
       progress += 8;
   } while (dst_pte++, src_pte++, addr += PAGE_SIZE, addr != end);

   arch_leave_lazy_mmu_mode();
   spin_unlock(src_ptl);
   pte_unmap(orig_src_pte);
   add_mm_rss_vec(dst_mm, rss);
   pte_unmap_unlock(orig_dst_pte, dst_ptl);
   cond_resched();

   if (entry.val) {
       if (add_swap_count_continuation(entry, GFP_KERNEL) < 0)
           return -ENOMEM;
       progress = 0;
   }
   if (addr != end)
       goto again;
   return 0;
}

問題

  1. 在 中,變數do {} while()的用途是什麼?
  2. 之後,為什麼需要它?這是 的過程。根據我的知識,仍應映射父級,因為該過程基於寫時複製,所以我想不必取消映射。progress
    do {} while()``pte_unmap(orig_src_pte);``fork()``pte(orig_src_pte)
  1. progress變數衡量在鎖下執行的操作的成本,並避免持有這些鎖太久。最多每 32 次呼叫pte_none,或 4 次呼叫copy_one_pte(代價高昂),或兩者的組合,該函式檢查是否需要重新調度,或者是否在其他地方請求了鎖;如果是這樣,它會釋放鎖並允許重新安排。由於跳轉到again.
  2. unmap 呼叫不會取消映射源程序中的原始 PTE,它會撤消src_pte = pte_offset_map(src_pmd, addr);函式開頭的行的影響。

引用自:https://unix.stackexchange.com/questions/507868