linux内存管理-页面规整
頁面規(guī)整
背景
linux長時間運行后,可能會發(fā)生頁面申請失敗,原因有兩種情況:
對于第一種情況主要通過頁面回收的方式來回收到足夠的內(nèi)存頁,包括釋放干凈的文件映射頁,回寫臟頁,匿名頁到swap方式回收到可用的物理內(nèi)存,但是第二種情況就比較復(fù)雜。
系統(tǒng)長時間運行后,不斷的申請和釋放頁,最終可能是有可用的內(nèi)存,但是缺少連續(xù)的物理內(nèi)存,就是內(nèi)存碎片,就和上圖一樣。雖然buddy以簡單的方式能夠很好的維護連續(xù)空閑頁,但是它并對內(nèi)存碎片問題并沒有解決方式。而且內(nèi)存碎片問題也無法徹底解決,目前有兩種方式能夠緩解這個問題:
頁面規(guī)整的原理
reflink:https://lwn.net/Articles/368869/
頁面碎片如上圖所示,白色代表空閑頁,紅色代表使用的頁。現(xiàn)在雖然有8個page的空閑內(nèi)存,但是無法申請連續(xù)的4個頁面,而且申請連續(xù)的2個頁面都不行,buddy管理的頁面中他們都不符合合并的規(guī)則,只有8個order=0的頁。
頁面規(guī)整的整體算法:以zone為規(guī)整對象,其中每次掃描又以pageblock為單位進行掃描。它有兩個指針:從zone頭部開始的migrate和從zone尾部開始的free,首先從頭部收集一批可移動的頁,然后從尾部收集一批空閑頁,將可移動頁遷移到尾部的空閑頁中,最后當migrage和free在中間相遇時,前半部分已經(jīng)沒有可移動的頁,后半部分沒有了空閑頁,退出整個規(guī)整過程。
從頭部掃描可移動頁:
從尾部掃描空閑頁:
頁面規(guī)整之后的結(jié)果:
上面展示了非常理想的工作過程。但是并不是所有的頁都可移動的,只有那些可以通過頁表訪問的頁并且沒有被lock的頁才可以移動,這些頁基本上都是應(yīng)用進程使用的頁,而內(nèi)核的頁大部分都是不可移動的,但是其中的一部分是可回收的,在需要的時候直接釋放掉。往往一個不可移動的頁就能破壞一大片連續(xù)內(nèi)存的連續(xù)性,不過內(nèi)核中的遷移類型機制最大限度的隔離了不可移動的頁和可移動頁的,內(nèi)存規(guī)整的效果是依賴于遷移類型機制的。
頁面規(guī)整主要有兩種觸發(fā)方式:
頁面規(guī)整的實現(xiàn)
頁面規(guī)整有兩種模式:異步和同步,在頁面回收失敗的時候首先開啟異步的頁面規(guī)整,如果異步頁面規(guī)整不出滿足要求的內(nèi)存,接下來使用嘗試通過直接內(nèi)存回收方式回收到足夠的內(nèi)存,如果還是獲取不到足夠的連續(xù)內(nèi)存,那么再次嘗試通過同步頁面規(guī)整的方式獲取連續(xù)內(nèi)存。
頁面規(guī)整的對象類型有兩種遷移類型:MIGRATE_RECLAIMABLE,MIGRATE_MOVABLE,從規(guī)整方式來看有兩種:匿名映射和文件映射類型的頁。
異步頁面規(guī)整只規(guī)整匿名頁,而同步頁面規(guī)整還會處理文件臟頁,如果頁面正在回寫,它還會等待頁面完成回寫。
異步頁面規(guī)整相對來說比較保守,匿名頁的頁面遷移只需要將頁的內(nèi)容遷移到新頁中,創(chuàng)建新的映射關(guān)系,解除舊的映射關(guān)系,全是內(nèi)存的讀寫操作,而同步還涉及到IO回寫,它的耗時更長。
外部碎片嚴重程度的計算
系統(tǒng)通過/sys/kernel/debug/extfrag/unusable_index導(dǎo)出了外部碎片的概率,從0-1,這個值越高代表有連續(xù)可用內(nèi)存的概率越小,外部碎片問題越嚴重,當申請2^order頁時越困難。
統(tǒng)計0-order中空閑頁的總數(shù)量和各個階鏈表上空閑塊的總數(shù),當空閑頁數(shù)量一定時,如果低階的空閑頁數(shù)量越多,則block值越高,則最后的碎片化也越嚴重;如果高階的空閑頁數(shù)量多,則block相對較小,碎片化整理起來難度相對更加容易
頁面規(guī)整實現(xiàn)過程
開始從zone的頭部開始掃描pageblock,如果是異步規(guī)整模式,則只隔離MIGRATE_MOVABLE中的匿名頁,將它從LRU中隔離到migratepages中,一次最大COMPACT_CLUSTER_MAX個頁,掃描完成后記錄當前掃描的位置migrate_pfn,這樣小塊的頁面遷移方便在回收失敗的時候?qū)⒏綦x頁重新返回到LRU鏈表中。
對于文件映射的臟頁,如果不是同步模式頁面規(guī)整,則不進行回寫,如果該頁面正在回寫,也不等待回寫完成。如果是同步模式則對于臟頁需要回寫,并且等待正在回寫頁的完成。
遷移總共分三部分,中間比較復(fù)雜,涉及到反向映射的實現(xiàn):
頁面規(guī)整的結(jié)束條件
對于重復(fù)進行頁面規(guī)整的避免
zone中記錄了頁面規(guī)整的狀態(tài),compact_defer_shift定義了頁面規(guī)整的閾值,compact_considered標記當前已經(jīng)推遲了多少次的頁面規(guī)整請求。
當頁面規(guī)整后仍然無法滿足頁面申請的需求,對zone進行標記compact_defer_shift;如果接下來繼續(xù)發(fā)起了頁面規(guī)整,則不會再頻繁的發(fā)起頁面規(guī)整,它認為短時間內(nèi)頁面規(guī)整不會有太大的效果,這時候會記錄推遲了多少次的規(guī)整請求compact_considered,當發(fā)起的請求超過閾值之后才會再次發(fā)起規(guī)整請求。
當頁面規(guī)整滿足了頁面申請后會重置閾值和推遲請求次數(shù)。
總結(jié)
以上是生活随笔為你收集整理的linux内存管理-页面规整的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 全新8.6版本SEO快排系统(可源码级搭
- 下一篇: C4D学习笔记2-动画-时间线及时间函数