![커널의 copy_pte_range()에 대한 두 가지 질문](https://linux55.com/image/150434/%EC%BB%A4%EB%84%90%EC%9D%98%20copy_pte_range()%EC%97%90%20%EB%8C%80%ED%95%9C%20%EB%91%90%20%EA%B0%80%EC%A7%80%20%EC%A7%88%EB%AC%B8.png)
나는 그것이 어떻게 작동하는지 이해하려고 노력했고 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
이
progress
변수는 잠금 상태에서 수행되는 작업 비용과 이러한 잠금을 너무 오랫동안 유지하는 것을 방지하는 비용을 측정합니다. 최대 32번의 호출pte_none
, 4번의 호출copy_one_pte
(비싼 비용) 또는 그 조합마다 함수는 일정 조정이 필요한지 또는 잠금이 다른 곳에서 요청되었는지 여부를 확인하고 필요한 경우 잠금을 해제하고 일정 변경을 허용합니다. 으로 점프하기 때문에 함수는 중단된 위치부터 계속됩니다again
.unmap 호출은 소스 프로세스에서 원래 PTE의 매핑을 해제하지 않으며
src_pte = pte_offset_map(src_pmd, addr);
함수 시작 부분의 줄 효과를 취소합니다.