頁面回收的基本概念
作者:linuxer 發佈於:2017-8-25 19:01 分類:記憶體管理
本文主要介紹了一些page reclaim機制中的基本概念。這份文檔其實也可以看成閱讀ULK第17章第一小節的一個讀書筆記。雖然ULK已經讀了很多遍,不過每一遍還是覺得有收穫。Linux核心雖然不斷在演化,但是頁面回收的基本概念是不變的,所以ULK仍然值得核心發燒友仔細品味。
一、什麼是page frame reclaiming。
在使用者進程的記憶體使用量上,Linux核心並沒有嚴格的限制,其實思路是:當系統負荷小的時候,記憶體都是位於各種cache中,以便提高效能。當系統負荷重(進程數目非常多)的時候,cache中的記憶體被收回,然後用於進程地址空間的建立和映射。在這樣思路的指導下,一開始,核心大手大腳,一直從夥伴系統的free list上分配page frame給使用者進程或者各種kernel cache使用,但是系統記憶體終歸是有限的,當夥伴系統的空閑記憶體下降到一定的水位的時候,系統會從使用者進程或者kernel cache中回收page frame到夥伴系統,以便滿足新的記憶體配置的需求,這個過程就是page frame reclaiming。一言以蔽之,page frame reclaiming就是保證系統的空閑記憶體在一個指定的水位之上。
二、什麼時候啟動page frame reclaiming。
能不能等到空閑記憶體用盡之後才啟動page frame reclaiming呢。不行,因為在page frame reclaiming的過程中也會消耗記憶體(例如在頁面回收過程中,我們可能會將page frame的資料交換到磁碟,因此需要分配buffer head資料結構,完成IO操作),因此我們必須在夥伴系統中保持一定的水位,以便讓page frame reclaiming機制正常工作,以便回收更多的記憶體,讓系統運轉下去,否則系統會crash掉。
三、哪些情境可以觸發page frame reclaiming。
當分配記憶體失敗的時候觸發頁面回收是最直觀的想法,然而核心的情境沒有那麼簡單,例如在中斷上下文中分配記憶體,這時候我們不能觸發page frame reclaiming,因為這時候我們不能阻塞當前進程。此外,有些記憶體配置的情境是發生在持鎖之後(以便對某些資源進行排他性的訪問),這時候,我們也不能啟用IO操作,進行記憶體回收。
因此,總結起來,核心在記憶體回收的思路就是:系統在分配記憶體的時候就進行檢查,如果有需要就喚醒kswapd,讓系統的空閑記憶體的數量保持在一個水平之上,以免將自己逼入絕境。如果沒有辦法,的確進入了絕境(分配記憶體失敗),那麼就直接觸發頁面回收。具體的情境包括:
1、synchronous page reclaim,即當遭遇分配記憶體失敗的時候,一言不合,然後直接調用page frame reclaiming進行回收。例如:在分配page buffer的時候(alloc_page_buffers),如果分配不成功,直接調用free_more_memory進行記憶體回收。或者在調用__alloc_pages的時候,如果分配不成功,直接調用try_to_free_pages進行記憶體回收。當然,其實free_more_memory也是調用try_to_free_pages來實現頁面回收的。
2、Suspend to disk(Hibernation)的情境。系統hibernate的時候需要大量記憶體,這時候會調用shrink_all_memory來回收指定數目的page frame。
3、kswapd情境。Kswapd是一個專門用來進行頁面回收的核心線程。
4、slab記憶體 Clerk會定時的queue work到system_wq上去,從而會周期性的調用cache_reap來回收slab上的空閑記憶體。
四、頁面回收的策略為何。
首先我們需要對page frame進行分類,主要分成4類:
1、 沒有辦法回收的page frame。包括空閑頁面(已經在free list上面,也就不需要勞駕page frame reclaim機制了)、保留頁面(設定了PG_reserved,例如核心本文段、資料區段等等)、核心動態分配的page frame、使用者進程的核心棧上的page frame、臨時性的被鎖定的page frame(即設定了PG_locked flag,例如在進行磁碟IO的時候)、mlocked page frame(有VM_LOCKED標識的VMA)
2、 可以交換到磁碟的page frame(swappable)。使用者空間的匿名映射頁面(使用者進程堆和棧上的page frame)、tmpfs的page frame。
3、 可以同步到磁碟的page frame(syncable)。使用者空間的檔案對應(file mapped)頁面,page cache中的page frame(其內容會對應到某個磁碟檔案),block device的buffered cache、disk cache中的page frame(例如inode cache)
4、 可以直接釋放的page frame。各種記憶體cache(例如 slab記憶體 Clerk)中還沒有使用的那些page frame、沒有使用的dentry cache。
上面的第二類和第三類有些類似, 其page frame都有後備檔案或者磁碟,不過我們可以這麼區分。Swappable的page frame,其資料的最終地點就是記憶體,其後備檔案或者磁碟只是為了延伸記憶體的容量。Syncable的page frame,其資料的最終地點就是磁碟,記憶體只不過是為了加快速度而已。因此,當回收swappable的頁面的時候,需要將page frame的資料儲存到後備的磁碟或者檔案。而當回收syncable頁面的時候,要看page frame是否是dirty的,如果dirty,則需要磁碟操作,否則可以直接回收。
圈定進行頁面回收的那些候選page frame很容易(即上面的2、3、4類型的page frame),但是怎麼考慮頁面回收的先後順序呢。Linux核心設定的基本規則如下:
1、 盡量不要修改page table。例如回收各種沒有使用的核心cache的時候,我們直接回收,根本不需要修改頁表項。而使用者空間進程的頁面回收往往涉及將對應的pte條目修改為無效狀態。
2、 除非調用mlock將page鎖定,否則所有的使用者空間對應的page frame都應該可以被回收。
3、 如果一個page frame被多個進程共用,那麼我們需要清除所有的pte entry,之後才能回收該頁面。
4、 不要回收那些最近使用(訪問)過的page frame,或者說優先回收那些最近沒有訪問的page frame。
5、 盡量先回收那些不需要磁碟IO操作的page frame。
原創文章,轉寄請註明出處。蝸窩科技,www.wowotech.net。