核心如何在磁碟記憶體和交換之間做出決定?
繼其他問題中提出的主題之後,我相信當 Linux 核心試圖釋放物理 RAM 時,它會在從磁碟記憶體中丟棄頁面或將其他頁面刷新到交換中做出某種決定。 我不確定這一點,也許我完全誤解了機制。
無論如何,兩者之間存在協同作用:
- 核心保持它自己的內部磁碟記憶體
- 程序記憶體映射文件
- “正常”應用程序記憶體被放置在交換文件中
這三個都可以用來釋放物理 RAM,這三個都依賴於將“臟”頁面寫入磁碟,或者只是知道這些頁面已經在磁碟上完全複製並從物理 RAM 分配中丟棄它們。
使用交換空間,可以為各個交換分區和文件賦予優先級,以便在使用較慢設備之前使用較快的設備。我不知道其他非交換設備的任何此類配置。
我的問題是:核心如何決定要釋放哪些 RAM?
它純粹基於最後一次訪問嗎?
核心是否平等地使用上述所有三個?
- 它們(和單個磁碟)之間是否有任何優先級
- 它是可配置的嗎?
這個問題由與此類似的經驗驅動,但我希望這個問題關注底層機製而不是解決特定問題。
釋放物理記憶體頁的整個任務的名稱是回收,它涵蓋了許多任務。回收主要由頁面分配驅動,具有不同程度的緊迫性。在解除安裝的系統上,頁面分配可以毫不費力地得到滿足,並且不會觸發任何回收。在中等負載的系統上,仍然可以立即滿足頁面分配,但它們也會導致
kswapd
被喚醒以執行後台回收。在無法立即滿足頁面分配的已載入系統上,同步執行回收。可回收頁面是儲存可以在其他地方找到或可用的內容的頁面。這就是典型的平衡行為發揮作用的地方:內容也在文件中(或應該以文件結尾)的記憶體,v. 內容不在的記憶體(並且需要換出)。前者儲存在頁面記憶體中,後者不儲存,這就是為什麼平衡解釋通常談論頁面記憶體v.交換。
在核心中的一個位置確定優先於另一個的決定,
get_scan_count
由 中的設置控制struct scan_control
。該函式的目的描述如下:確定掃描匿名和文件 LRU 列表的積極程度。每組 LRU 列表的相對值是通過查看我們確實旋轉回活動列表而不是驅逐的掃描頁面的比例來確定的。
對於名為 的函式
get_...
,這可能令人驚訝,它不使用返回值;相反,它填充unsigned long *nr
指針指向的數組,其中四個條目對應於匿名非活動頁面(未支持,最近未使用的頁面),匿名活動頁面(未支持,最近使用的頁面),文件不活動頁面(頁面記憶體中最近未使用的頁面)和文件活動頁面(頁面記憶體中最近使用的頁面)。
get_scan_count
首先從 檢索適當的“swappiness”值mem_cgroup_swappiness
。如果目前記憶體 cgroup 是已啟用的非 root v1 cgroup,則使用其 swappiness 設置;否則,就是臭名昭著的/proc/sys/vm/swappiness
。兩種設置的目的相同;他們告訴核心帶回換出的匿名頁面與重新載入文件系統頁面的相對 IO 成本
在它實際使用這個值之前,
get_scan_count
確定它應該應用的整體策略:
- 如果沒有交換,或者在目前上下文中無法回收匿名頁面,它將只處理文件支持的頁面;
- 如果記憶體 cgroup 完全禁用交換,它將只處理文件支持的頁面;
- 如果沒有禁用swappiness(設置為0),並且系統幾乎沒有記憶體,它將平等地處理所有頁面;
- 如果系統幾乎沒有文件頁面,它將只查找匿名頁面;
- 如果有足夠的非活動頁面記憶體,它將只處理文件支持的頁面;
- 在所有其他情況下,它會根據相應的 I/O 成本調整賦予各種 LRU 的“權重”。
一旦確定了策略,它就會遍歷所有可驅逐的 LRU(不活動匿名、活動匿名、不活動文件支持、活動文件支持,按此順序)以確定應該掃描每個 LRU 的多少頁;我將忽略 v1 cgroups:
- 如果策略是“平等地追踪所有頁面”,則所有 LRU 中的所有頁面都可能被掃描,直到由
scan_control
的priority
移位因子確定的大小;- 如果策略是“僅查找文件支持的頁面”或“僅查找匿名頁面”,則相應 LRU 中的所有頁面都是候選頁面(再次,移位
priority
),其他 LRU 中沒有;- 否則,這些值會根據 swappiness 進行調整。
實際的頁面掃描由 驅動
shrink_lruvec
,它使用上面確定的掃描長度,並反複收縮LRU,直到達到目標(以各種方式調整目標)。完成此操作後,將重新平衡活動/非活動 LRU。回到你的問題:
- 頁面記憶體和記憶體映射文件被同等對待;
- 頁面回收不是純粹基於上次訪問(我沒有解釋 LRU 是如何使用的,或者重新平衡是如何工作的;有關詳細資訊,請閱讀Mel Gorman 的了解 Linux 虛擬記憶體管理器中的相應章節);
- 核心沒有平等地使用它們;根據情況,它們的優先級不同,並且可以通過許多控制項(
swappiness
、cgroups、低水印門檻值…)進行配置。交換優先級僅確定頁面在決定將其換出後的去向。(順便說一句,
swappiness
上面的文件和解釋應該清楚地表明,I/O 成本沒有足夠的粒度來很好地處理混合 ZRAM/磁碟交換設置……)還有很多要解釋的,包括如何
scan_control
設置,但我懷疑這已經太長了!如果您想跟踪回收成本,您可以在任務延遲會計中看到它(另請參閱struct taskstats
)。