日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux内存管理-页面规整

發布時間:2023/12/8 linux 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux内存管理-页面规整 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

頁面規整

背景

linux長時間運行后,可能會發生頁面申請失敗,原因有兩種情況:

  • 空閑頁不夠,觸及到回收的閾值
  • 申請order > 0的連續頁時找不到連續的物理內存
  • 對于第一種情況主要通過頁面回收的方式來回收到足夠的內存頁,包括釋放干凈的文件映射頁,回寫臟頁,匿名頁到swap方式回收到可用的物理內存,但是第二種情況就比較復雜。

    系統長時間運行后,不斷的申請和釋放頁,最終可能是有可用的內存,但是缺少連續的物理內存,就是內存碎片,就和上圖一樣。雖然buddy以簡單的方式能夠很好的維護連續空閑頁,但是它并對內存碎片問題并沒有解決方式。而且內存碎片問題也無法徹底解決,目前有兩種方式能夠緩解這個問題:

  • 將zone進一步分為幾種類型:UNMOVABLE,RECLAIMABLE,MOVABLE等,通過在申請的時候表明申請頁的使用傾向,通過在不同區間中申請頁,防止長期使用的UNMOVABLE類型的頁破壞空閑物理內存的連續性。
  • 對頁面進行規整,在申請內存失敗的時候首先進行內存規整,主要是移動物理頁的內容并更新映射關系,釋放可回收的頁,這樣通過積極調整頁的位置來使得物理內存連續。
  • 頁面規整的原理

    reflink:https://lwn.net/Articles/368869/


    頁面碎片如上圖所示,白色代表空閑頁,紅色代表使用的頁。現在雖然有8個page的空閑內存,但是無法申請連續的4個頁面,而且申請連續的2個頁面都不行,buddy管理的頁面中他們都不符合合并的規則,只有8個order=0的頁。

    頁面規整的整體算法:以zone為規整對象,其中每次掃描又以pageblock為單位進行掃描。它有兩個指針:從zone頭部開始的migrate和從zone尾部開始的free,首先從頭部收集一批可移動的頁,然后從尾部收集一批空閑頁,將可移動頁遷移到尾部的空閑頁中,最后當migrage和free在中間相遇時,前半部分已經沒有可移動的頁,后半部分沒有了空閑頁,退出整個規整過程。

    從頭部掃描可移動頁:

    從尾部掃描空閑頁:

    頁面規整之后的結果:

    上面展示了非常理想的工作過程。但是并不是所有的頁都可移動的,只有那些可以通過頁表訪問的頁并且沒有被lock的頁才可以移動,這些頁基本上都是應用進程使用的頁,而內核的頁大部分都是不可移動的,但是其中的一部分是可回收的,在需要的時候直接釋放掉。往往一個不可移動的頁就能破壞一大片連續內存的連續性,不過內核中的遷移類型機制最大限度的隔離了不可移動的頁和可移動頁的,內存規整的效果是依賴于遷移類型機制的。

    頁面規整主要有兩種觸發方式:

  • 通過proc節點/proc/sys/vm/compact_node向用戶空間提供了主動干預規整的接口
  • 申請order >0的頁失敗時,這時候是首先嘗試進行頁面規整,如果還是不能提供滿足連續頁面申請的請求則進行直接頁面回收。
  • 頁面規整的實現

    頁面規整有兩種模式:異步和同步,在頁面回收失敗的時候首先開啟異步的頁面規整,如果異步頁面規整不出滿足要求的內存,接下來使用嘗試通過直接內存回收方式回收到足夠的內存,如果還是獲取不到足夠的連續內存,那么再次嘗試通過同步頁面規整的方式獲取連續內存。

    頁面規整的對象類型有兩種遷移類型:MIGRATE_RECLAIMABLE,MIGRATE_MOVABLE,從規整方式來看有兩種:匿名映射和文件映射類型的頁。

    異步頁面規整只規整匿名頁,而同步頁面規整還會處理文件臟頁,如果頁面正在回寫,它還會等待頁面完成回寫。
    異步頁面規整相對來說比較保守,匿名頁的頁面遷移只需要將頁的內容遷移到新頁中,創建新的映射關系,解除舊的映射關系,全是內存的讀寫操作,而同步還涉及到IO回寫,它的耗時更長。

    外部碎片嚴重程度的計算
    系統通過/sys/kernel/debug/extfrag/unusable_index導出了外部碎片的概率,從0-1,這個值越高代表有連續可用內存的概率越小,外部碎片問題越嚴重,當申請2^order頁時越困難。

    統計0-order中空閑頁的總數量和各個階鏈表上空閑塊的總數,當空閑頁數量一定時,如果低階的空閑頁數量越多,則block值越高,則最后的碎片化也越嚴重;如果高階的空閑頁數量多,則block相對較小,碎片化整理起來難度相對更加容易

    static void fill_contig_page_info(struct zone *zone,unsigned int suitable_order,struct contig_page_info *info) {for (order = 0; order < MAX_ORDER; order++) {unsigned long blocks;/* 累計各個階的空閑塊數 */blocks = zone->free_area[order].nr_free;info->free_blocks_total += blocks;/* 空閑頁的數量 */info->free_pages += blocks << order;/* 如果在這個階上有空閑頁,肯定是沒有碎片的 */if (order >= suitable_order)info->free_blocks_suitable += blocks <<(order - suitable_order);} } static int __fragmentation_index(unsigned int order, struct contig_page_info *info) {unsigned long requested = 1UL << order;//數值從0-1,保留兩位小數,總共就是3位有效數字,轉換成0-1000.//越靠近1000說明碎片化越嚴重,0標明缺乏空閑內存if (!info->free_blocks_total)return 0;/* Fragmentation index only makes sense when a request would fail */if (info->free_blocks_suitable)return -1000;return 1000 - div_u64( (1000+(div_u64(info->free_pages * 1000ULL, requested))), info->free_blocks_total); }/* Same as __fragmentation index but allocs contig_page_info on stack */ int fragmentation_index(struct zone *zone, unsigned int order) {struct contig_page_info info;fill_contig_page_info(zone, order, &info);return __fragmentation_index(order, &info); }

    頁面規整實現過程

  • 頁面遷移功能中將zone進一步分成pageblock,每個block代表連續的物理內存頁,分配一片bitmap的pageblock_flags,每個block占據3個bit,表示當前的遷移類型
  • enum pageblock_bits {PB_migrate, PB_migrate_end = PB_migrate + 3 - 1,/* 3 bits required for migrate types */NR_PAGEBLOCK_BITS };
  • 隔離頁
    開始從zone的頭部開始掃描pageblock,如果是異步規整模式,則只隔離MIGRATE_MOVABLE中的匿名頁,將它從LRU中隔離到migratepages中,一次最大COMPACT_CLUSTER_MAX個頁,掃描完成后記錄當前掃描的位置migrate_pfn,這樣小塊的頁面遷移方便在回收失敗的時候將隔離頁重新返回到LRU鏈表中。
  • 從zone的尾部找空閑頁,需要滿足同樣隔離頁的遷移性,異步頁面規整時只掃描MIGRATE_MOVABLE的block,當free和migrate的指針相遇時或者獲取到足夠遷移當前隔離的頁結束收集空閑頁。掃描空閑頁一次性掃描一個pageblock區間的頁,它得到的空閑頁數量可能是大于當前隔離頁的數量的,這樣這次批量遷移完成下次還有空閑頁可用。最后掃描空閑頁的時候,migrate_pfn和free_pfn可能相差
  • 遷移頁
    對于文件映射的臟頁,如果不是同步模式頁面規整,則不進行回寫,如果該頁面正在回寫,也不等待回寫完成。如果是同步模式則對于臟頁需要回寫,并且等待正在回寫頁的完成。
    遷移總共分三部分,中間比較復雜,涉及到反向映射的實現:
  • 解除需要遷移頁的映射關系,即pte 拷貝遷移頁內容和page的狀態到新的頁中page中 建立新的映射關系,即設置新的pte
  • 對于最終沒有遷移的頁或者空閑頁,最終會恢復原狀,migratepages再次加入到LRU鏈表中,freepage再次還回到buddy系統中


  • 頁面規整的結束條件

  • 滿足連續物理內存的申請,不需要繼續規整就已經滿足本次的頁面申請了
  • 整個zone都已經掃描一遍,沒有可以規整的頁面了
  • 對于重復進行頁面規整的避免

    zone中記錄了頁面規整的狀態,compact_defer_shift定義了頁面規整的閾值,compact_considered標記當前已經推遲了多少次的頁面規整請求。
    當頁面規整后仍然無法滿足頁面申請的需求,對zone進行標記compact_defer_shift;如果接下來繼續發起了頁面規整,則不會再頻繁的發起頁面規整,它認為短時間內頁面規整不會有太大的效果,這時候會記錄推遲了多少次的規整請求compact_considered,當發起的請求超過閾值之后才會再次發起規整請求。
    當頁面規整滿足了頁面申請后會重置閾值和推遲請求次數。

    總結

    以上是生活随笔為你收集整理的linux内存管理-页面规整的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。