1. 程式人生 > >Linux頁面回收概述

Linux頁面回收概述

需求 都是 發生 div nat end ber app cache

本文主要介紹了一些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內存分配器會定時的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內存分配器)中還沒有使用的那些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。

Linux頁面回收概述