do_swap_page函数

前面已经讲过,当pte所对应的page不在内存中,且pte对应的内容不为0时,表示此时pte的内容所对应的页面在swap空间中,缺页异常时会通过do_swap_page()函数来分配页面:

static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
		unsigned long address, pte_t *page_table, pmd_t *pmd,
		unsigned int flags, pte_t orig_pte)
{
…………
	entry = pte_to_swp_entry(orig_pte);----------(1)
	page = lookup_swap_cache(entry);----------(2)
	if (!page) {
		page = swapin_readahead(entry,
					GFP_HIGHUSER_MOVABLE, vma, address);-------(3)
…………
		ret = VM_FAULT_MAJOR;
		count_vm_event(PGMAJFAULT);-------------(4)
…………
        }
	locked = lock_page_or_retry(page, mm, flags);--------------(5)
…………
	page_table = pte_offset_map_lock(mm, pmd, address, &ptl);--------------(6)
…………
	inc_mm_counter_fast(mm, MM_ANONPAGES);--------------(7)
	dec_mm_counter_fast(mm, MM_SWAPENTS);---------------(8)
	pte = mk_pte(page, vma->vm_page_prot);

	set_pte_at(mm, address, page_table, pte);---------------(9)
	if (page == swapcache) {---------(10)
		do_page_add_anon_rmap(page, vma, address, exclusive);
		mem_cgroup_commit_charge(page, memcg, true);
	} else { /* ksm created a completely new copy */
		page_add_new_anon_rmap(page, vma, address);-------------------(11)
		mem_cgroup_commit_charge(page, memcg, false);
		lru_cache_add_active_or_unevictable(page, vma);------------------(12)
	}
…………
}

(1)根据pte来获取swap的entry,swap entry和pte有一个对应关系,和__SWP_TYPE_SHIFT  __SWP_TYPE_BITS两个宏相关,具体对应关系,这里不做深究

(2)在swapcache里面寻找entry对应的page

(3)如果swapcache里面找不到就在swap area里面找

(4)PGMAJFAULT计数加1

(5)尝试给page上锁

(6)获取一个pte entry

(7)anonpage数加1,匿名页从swap空间交换出来,所以加1

(8)swap page个数减1,由page和VMA属性创建一个新的pte。

(9)将新生成的PTE entry添加到硬件页表

(10)根据page是否为swapcache,如果是,则只为page创建rmap,如果不是则创建rmap还要将page添加到LRU链表。

总结一下:整个过程就是由pte得到swap entry,再由swap entry得到page,再由pte以及pte entry添加到硬件pte页表。

另外这里由关于swapcache的概念,在网上找的,讲得比较好:

这个swap cache的作用不是说要加快磁盘的I/O效率,主要是为了防止页面在swap in和swap out时,进程的同步问题,也就是在进行swap out操作时(将页面内容写入磁盘分区时)进程如果发起了对换出页面的访问,系统对其的处理。有了swap cache的存在,如果页面的数据还没有完全写入磁盘时,这个page frame是在swap cache(swap cache有个引用指向页面),等数据完全写入磁盘后,而且没有进程对page frame进行访问,那么swap cache才会释放page frame,将其交给buddy system.

并不是每一个匿名页都在swap cache中,只有以下情形之一的匿名页才在:

  • 匿名页即将被swap-out时会先被放进swap cache,但通常只存在很短暂的时间,因为紧接着在pageout完成之后它就会从swap cache中删除,毕竟swap-out的目的就是为了腾出空闲内存;
    【注:参见mm/vmscan.c: shrink_page_list(),它调用的add_to_swap()会把swap cache页面标记成dirty,然后它调用try_to_unmap()将页面对应的page table mapping都删除,再调用pageout()回写dirty page,最后try_to_free_swap()会把该页从swap cache中删除。】
  • 曾经被swap-out现在又被swap-in的匿名页会在swap cache中,直到页面中的内容发生变化、或者原来用过的交换区空间被回收为止。
    【注:当匿名页的内容发生变化时会删除对应的swap cache,代码参见mm/swapfile.c: reuse_swap_page()。】

SwapCached背后的含义是:系统中有多少匿名页曾经被swap-out、现在又被swap-in并且swap-in之后页面中的内容一直没发生变化。也就是说,如果这些匿名页需要被swap-out的话,是无需进行I/O write操作的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章