カーネルの copy_pte_range() に関する 2 つの質問

カーネルの copy_pte_range() に関する 2 つの質問

私はそれがどのように機能するかを理解しようとし、fork()ついに到着しましたcopy_pte_range()。ほとんどの機能は理解できますが、疑わしいことはほとんどありません。

コア:1984年4月14日

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

  1. このprogress変数は、ロック状態で実行される作業コストと、これらのロックを長期間維持するのを防ぐコストを測定します。最大32回の呼び出しpte_none、4回の呼び出しcopy_one_pte(高価)、またはその組み合わせごとに、関数はスケジューリングが必要かどうかを確認し、必要に応じてロックを解除してスケジュールの変更を許可します。にジャンプするため、関数は中断された位置から続きますagain

  2. unmap 呼び出しは、ソース・プロセスから元の PTE のマッピングを解放せず、src_pte = pte_offset_map(src_pmd, addr);関数の先頭の行効果を取り消します。

おすすめ記事