页表的释放

页表在必要的时候还需要释放:比如进程销毁或者munmap。

看过了页表构造的过程(虽然糙了点),那也该看看页表释放的过程。面这个函数是我找到的接口之一。

vms_clear_ptes(vms, mas_detach, mm_wr_locked)
    struct mmu_gather tlb;
    tlb_gather_mmu(&tlb, vms->vma->vm_mm)
        inc_tlb_flush_pending(mm)
    unmap_vmas(&tlb, mas_detach, vms->vma, vms->start, vms->end, vms->vma_count)
        unmap_single_vma(tlb, vma, start, end, &details)
            unmap_page_range(tlb, vma, start, end, detail)
                tlb_start_vma(tlb, vma)
                zap_p4d_range(tlb, vma, pgd, addr, next, )
                    zap_pte_range(tlb, )
                    pte_offset_map_lock(mm, pmd, addr, &ptl)          // lock page table
                        zap_present_ptes(tlb, )
                            nr = folio_pte_batch(folio, pte, ptent, max_nr)
                            zap_present_folio_ptes(tlb, folio, page, pte, ptent, nr, )
                    pte_unmap_unlock(, &ptl)                          // unlock page table
                tlb_end_vma(tlb, vma)
    free_pgtables(&tlb, mas_detach, vms->vma, vms->unmap_start, vms->unmap_end, )
        tlb_free_vmas(tlb)
        free_pgd_range(tlb, addr, vma->vm_end, floor, )
            tlb_change_page_size(tlb, PAGE_SIZE)
            free_p4d_range()
                free_pte_range(tlb, pmd, addr)
                pte_free_tlb(tlb, token, addr)
    tlb_finish_mmu(&tlb)
        dec_tlb_flush_pending(mm)

其中unmap_vmas释放了真正对应的内存,而free_pgtables才释放页表。

但是在页表释放的时候,其实有三件事情要做:

  • 清除PMD/PTE等页表项

  • 释放页表,归还到page allocator

  • tlb flush,告诉其他cpu取消(shootdown)对应的映射

mmu_gather

在整个页表释放的过程中,有一个贯穿始终的结构体mmu_gather,也就是函数中第一个参数tlb。

我们需要好好看看这个结构。

Last updated

Was this helpful?