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操作的。

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