本文共 2358 字,大约阅读时间需要 7 分钟。
反向映射是指根据struct page数据结构找到所有映射到这个page的vma,反向映射主要用于kswaped和页面迁移.反向映射主要调用try_to_unmap来进行其源码分析如下:bool try_to_unmap(struct page *page, enum ttu_flags flags){ struct rmap_walk_control rwc = { .rmap_one = try_to_unmap_one, .arg = (void *)flags, .done = page_mapcount_is_zero, .anon_lock = page_lock_anon_vma_read, }; /* * During exec, a temporary VMA is setup and later moved. * The VMA is moved under the anon_vma lock but not the * page tables leading to a race where migration cannot * find the migration ptes. Rather than increasing the * locking requirements of exec(), migration skips * temporary VMAs until after exec() completes. */ if ((flags & (TTU_MIGRATION|TTU_SPLIT_FREEZE)) && !PageKsm(page) && PageAnon(page)) rwc.invalid_vma = invalid_migration_vma; if (flags & TTU_RMAP_LOCKED) rmap_walk_locked(page, &rwc); else rmap_walk(page, &rwc); return !page_mapcount(page) ? true : false;}从上面可以看到如果page中包含TTU_RMAP_LOCKED则调用rmap_walk_locked 来断开映射到这个页面的vma,否则调用rmap_walk这里以rmap_walk为例void rmap_walk(struct page *page, struct rmap_walk_control *rwc){ if (unlikely(PageKsm(page))) rmap_walk_ksm(page, rwc); else if (PageAnon(page)) rmap_walk_anon(page, rwc, false); else rmap_walk_file(page, rwc, false);}从这个函数可以看到有二种场景会映射到page,分别是anon/file映射页面,通知不支持ksm映射页面这里以rmap_walk_anon为例static void rmap_walk_anon(struct page *page, struct rmap_walk_control *rwc, bool locked){ struct anon_vma *anon_vma; pgoff_t pgoff_start, pgoff_end; struct anon_vma_chain *avc;#根据page找到对应的anon_vma,这里有分为是否加锁两种情况 if (locked) { anon_vma = page_anon_vma(page); /* anon_vma disappear under us? */ VM_BUG_ON_PAGE(!anon_vma, page); } else { anon_vma = rmap_walk_anon_lock(page, rwc); } #如果没有找到对应的vma则退出 if (!anon_vma) return; #得到这个page的起始和结束的index,这里通过hpage_nr_pages考虑了hugepage的case pgoff_start = page_to_pgoff(page); pgoff_end = pgoff_start + hpage_nr_pages(page) - 1; #遍历anon_vma->rb_root anon_vma_interval_tree_foreach(avc, &anon_vma->rb_root, pgoff_start, pgoff_end) { #找到这段地址对应的vma struct vm_area_struct *vma = avc->vma; unsigned long address = vma_address(page, vma); cond_resched(); if (rwc->invalid_vma && rwc->invalid_vma(vma, rwc->arg)) continue; #调用try_to_unmap 中定义的rmap_one来断开vma和这个page的映射 if (!rwc->rmap_one(page, vma, address, rwc->arg)) break; if (rwc->done && rwc->done(page)) break; } if (!locked) anon_vma_unlock_read(anon_vma);}
转载地址:http://gjnmi.baihongyu.com/