精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何避免Linux的物理內存碎片化

Linux閱碼場 ? 來源:未知 ? 作者:伍文輝 ? 2018-05-01 16:43 ? 次閱讀

Linux buddyy系統是linux kernel比較穩定的一個模塊,但是并不是說它沒有缺陷,Linux內存管理系統自誕生之日,就一直存在物理內存碎片化的問題:在系統啟動并且運行很長一段時間后,極端情況下,盡管總的可用物理page數目很高,但是空閑的連續物理內存可能并不大,這就造成申請大塊連續物理內存分配時失敗。尤其是當分配操作帶有ATOMAIC標記時,系統連回收內存的機會都沒有。

避免碎片

很長時間以來,物理內存的碎片化一直是Linux操作系統的弱點之一,盡管已經有人提出了很多解決方法,但是沒有哪個方法能夠徹底的解決,memory buddy分配就是解決方法之一。 我們知道磁盤文件也有碎片化問題,但是磁盤文件的碎片化只會減慢系統的讀寫速度,并不會導致功能性錯誤,而且我們還可以在不影響磁盤功能的前提的下,進行磁盤碎片整理。而物理內存碎片則截然不同,物理內存和操作系統結合的太過于緊密,以至于我們很難在運行時,進行物理內存的搬移(這一點上,磁盤碎片要容易的多;實際上mel gorman已經提交了內存緊縮的patch,只是還沒有被主線內核接收)。 因此解決的方向主要放在預防碎片上。

在2.6.24內核開發期間,防止碎片的內核功能加入了主線內核。在了解反碎片的基本原理前,先對內存頁面做個歸類:

1. 不可移動頁面 unmoveable:在內存中位置必須固定,無法移動到其他地方,核心內核分配的大部分頁面都屬于這一類。

2. 可回收頁面 reclaimable:不能直接移動,但是可以回收,因為還可以從某些源重建頁面,比如映射文件的數據屬于這種類別,kswapd會按照一定的規則,周期性的回收這類頁面。

3. 可移動頁面 movable:可以隨意的移動。屬于用戶空間應用程序的頁屬于此類頁面,它們是通過頁表映射的,因此我們只需要更新頁表項,并把數據復制到新位置就可以了,當然要注意,一個頁面可能被多個進程共享,對應著多個頁表項。

防止碎片的方法就是把這三類page放在不同的鏈表上,避免不同類型頁面相互干擾。考慮這樣的情形,一個不可移動的頁面位于可移動頁面中間,那么我們移動或者回收這些頁面后,這個不可移動的頁面阻礙著我們獲得更大的連續物理空閑空間。

(圖片來源:https://images2015.cnblogs.com/blog/758933/201703/758933-20170301165125907-1024080699.png)

針對頁面的分類,我們引入了movable zone,事實上movable zone是虛擬zone,是在運行時逐漸建立的。當然內核的確可以建立真實的內存zone。

我們知道大部分buddy分配失敗,發生在申請unremovable頁面時。這樣分類還有一個潛在的好處,為unremovable保留的頁面,被reclaimable和movable分配的優先級低(參見fallbacks),因此客觀上減少了buddy分配unremovable頁面的幾率。

數據結構

kernel引入了一些宏來表示不同的遷移類型:

#define MIGRATE_UNMOVABLE 0#define MIGRATE_RECLAIMABLE 0#define MIGRATE_MOVALBE 0#define MIGRATE_RESERVE 0#define MIGRATE_ISOLATE 0#define MIGRATE_TYPES 0

類型MIGRATE_UNMOVABLE, MIGRATE_RECLAIMABLE和MIGRATE_MOVALBE就是我們上面介紹的三種頁面類型。如果向特定類型頁面分配請求失敗,緊急情況下可以從MIGRATE_RESERVE分配內存。

當制定類型的空閑列表無法滿足分配時,可以按照一定規則從其他類型空閑鏈表分配,這個次序用下面數據描述

static int fallbacks[MIRGRATE_TYPES][MIGRATE_TYPES-1] = { [MIGRATE_UNMOVABLE] = {MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE}, [MIGRATE_RECLAIMABLE] = {MIRGRATE_UNMOVABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE}, [MIGRATE_MOVABLE] = {MIRGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_RESERVE}, [MIGRATE_RESERVE] = {MIGRATE_RESERVE, MIGRATE_RESERVE, MIGRATE_RESERVE},}

和zone_list功能類似,當內核想要分配不可移動頁面,如果該鏈表為空,則優先選擇從RECLAIMABLE鏈表分配,然后是MOVABLE,最后使用RESERVE鏈表。

實際上,這種方法并不能解決我們的問題,因為用戶空間頁面映射以及內核申請RECLAIMABLE頁面的需求可能是無止境的,當MOVABLE和RECLAIMABLE鏈表無法滿足分配時,根據fallbacks會占用MIGRATE_UNMOVABLE鏈表,這就導致后面UNMOVABLE分配可能失敗。

So,我們可以修改fallbacks如下

static int fallbacks[MIRGRATE_TYPES][MIGRATE_TYPES-1] = { [MIGRATE_UNMOVABLE] = {MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE}, [MIGRATE_RECLAIMABLE] = {MIRGRATE_MOVABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE}, [MIGRATE_MOVABLE] = {MIRGRATE_RECLAIMABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE}, [MIGRATE_RESERVE] = {MIGRATE_RESERVE, MIGRATE_RESERVE, MIGRATE_RESERVE},}

禁止MOVABLE或者RECLAIMABLE失敗后嘗試從UNMOVABLE鏈表分配頁面,這樣可以保持UNMOVABLE不受非關鍵頁面分配的干擾。

注意:即便可移動分組特性已經編譯到內核中,但是只有當系統中有足夠內存可以分配給多個類型的鏈表時,該特性才有意義。這個足夠的含義由pageblock_order和pageblock_nr_pages來定義。當可用內存過少的時候,引入頁面遷移沒有任何好處,相反會增加系統負擔。系統會在 build_all_zonelist中進行檢查,如果沒有足夠內存,則關閉該特性。

在內存子系統初始化期間,memmap_init_zone負責處理內存域的page實列,所有的頁最初都標記為可移動的!

mm/page_alloc.cvoid __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone, unsigned long start_pfn, enum memmap_context context){ strcut page *page; unsigned long end_pfn = start_pfn+size; unsigned long pfn; for (pfn = start_pfn; pfn < end_pfn; pfn++) {? ? ? ? ... ? ? ? ?if ((pfn & (pageblock_nr_pages - 1))) ? ? ? ? ? ?set_pageblock_migratetype(page, MIGRATE_MOVABLE);? ? ? ...}

在進行內存分配時,如果沒有預定遷移類型的內存區。那么會嘗試從MOVABLE鏈表上獲取盡可能大的內存區,并轉換到相應的列表,由于獲取的內存區長度是最大的,因此不會向可移動內存區引入碎片。這種做法使得不同類型的頁面從不同的頁面范圍內分配,從而使得不同類型的內存分配比避免干擾。

內存分配器如何知道分配申請是哪種遷移類型呢,這需要所有內存申請提供相應的分配標記,如果需要分配可移動的內存頁,那么使用__GFP_MOVABLE,如果申請可回收的則使用__GFP_RECLAIMABLE。如果這些標記都沒有設置,則認為是UNMOVABLE的。

Virtual Movable Zone

這種方法是提前分配一個稱為ZONE_MOVABLE的內存zone,ZONE_MOVABLE內核特性必須由管理員顯示激活。其基本思想是:把物理內存劃分為兩個內存zone,一個用于可移動分配,另外一個用于不可移動分配。這樣不可移動內存域不會干擾可移動內存域引入碎片,而可移動內存域因此很容易滿足分配。

當然,如何劃分這兩個內存域,對系統管理員是個挑戰。

和系統中的其他內存域不同,ZONE_MOVABLE是一個虛擬的內存域,它的內存取自高端內存域或者普通內存域。ZONE_MOVABLE內存有兩種提取方式:

1. 用于可移動分配的內存平均分布到所有的內存節點上。

2. 只使用來自最高內存域的內存,在內存較多的32位系統上,這通常是ZONE_HIGHMEM。注意這也和ZONE_MOVABLE的使用者吻合,因為只有用戶頁面映射才算是MOVA LE的內存頁,而用戶頁面映射優先使用的也是HIGHMEM。

因此對于ZONE_MOVABLE我們可以使用如下策略:

1. 使能高端內存

2. ZONE_MOVABLE從HIGHMEM提取內存

3. 系統管理員估算ZONE_MOVABLE的大小,較小的ZONE_MOVABLE使得非movable ZONE有更多地物理內存。

ZONE_MOVABLE 使用者

因為ZONE_MOVABLE的使用者是帶有GFP_MOVABLE和GFP_HIGHMEM標記的內核分配(主要是應用程序的頁面映射)。

void *vmalloc(unsigned long size){ return __vmalloc_node_flags(size, -1, GFP_KERNEL | __GFP_HIGHMEM);}

結論

ZONE_MOVABLE和頁面分類方法相比,好處是很明顯的:固定UNMOVABLE zone的大?。撁娣诸愭湵硎莿討B生成的),UNMOVABLE zone供內核關鍵分配函數使用。系統頻繁申請的MOVABLE分配,不會導致unmovable zone的碎片化。但是缺點仍然很明顯,即RECLAIMABLE分配還是使用unmovable zone,頻繁的分配回收仍然使得unmovable zone碎片化。

所以看起來,ZONE_MOVABLE方法只是緩解了物理內存碎片化,但是并沒有完全解決。

對于某些特定的驅動,我們可以通過以下方式減少分配失敗的可能性。

1. 減少分配所需的連續頁面數目。

2. 如果內存申請操作對系統來說是關鍵操作(比如framebuffer,網絡傳輸buffer),不允許分配失敗,但是又無法做到1,那么可以考慮使用預分配的策略。

對于某些特定的項目,可以通過如下方法減少DMA內存分配失敗的可能性。

1. 禁止帶有GFP_HIGHMEM標記的內存分配在HIGHMEM zone 分配失敗后,進入DMA zone尋找合適的頁面。

2. 禁止對Normal zone分配失敗,進入DMA zone尋找合適頁面

HIGHMEM的使用者主要是應用程序的頁面映射和內核vmalloc分配,這兩種操作都不需要連續物理頁面,HIGHMEM zone并不關心物理內存碎片化,而且這兩種操作映射的頁面本身就是reclaimable,實在沒有必要再去占用Normal和DMA zone的物理頁面。

尤其在Android系統上,Android退出應用操作只是把應用退到后臺,并沒有釋放內存,當運行時間較長,啟動多個應用后,這些應用占滿HIGHMEM zone后,就會去占用Normal zone和Highmem zone的內存。在這里我們切斷zone_list,就是防止貪得無厭的Android應用和Vmalloc占據Normal和DMA zone。

此外,linux kernel本身對待cache(此cache不是物理cache,而是指buffer cache, inode cache, dentry cache)也是有求必應的,Normal zone分配完,就使用DMA zone,直到把DMA zone占完為止。因此我們實在是有必要禁止cache這種貪得無厭的東西進入DMA zone。

這種截斷的做法雖然背離了linux盡量使用系統內存的做法,但是卻保證了三個內存區 DMA zone, Normal zone, Highmem zone互不干擾。

lowmem_reserve

上面提到了切斷HIGHMEM zone分配失敗回退到Normal zone和DMA zone,以及切斷Normal zone失敗回退到DMA zone。具體做法是配置lowmem_reserve

通過配置lowmem_reserve的為1,使得本內存zone針對高端分配保留盡可能多的空間,來減少fallback分配,這里用減少而不是禁止是因為lowmem_reserve算法在某些內存配置下,無法完全禁止fallback。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11232

    瀏覽量

    208952
  • 碎片化
    +關注

    關注

    0

    文章

    5

    瀏覽量

    1707

原文標題:避免物理內存碎片化

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Linux內存管理是什么,Linux內存管理詳解

    Linux內存管理 Linux內存管理是一個非常復雜的過程,主要分成兩個大的部分:內核的內存管理和進程虛擬
    的頭像 發表于 05-11 17:54 ?5983次閱讀
    <b class='flag-5'>Linux</b>的<b class='flag-5'>內存</b>管理是什么,<b class='flag-5'>Linux</b>的<b class='flag-5'>內存</b>管理詳解

    linux內存相關知識科普

    linux 內存組織結構和頁面布局,內存碎片產生原因和優化算法。
    發表于 08-08 10:57 ?380次閱讀

    走進Linux內存系統探尋內存管理的機制和奧秘

    Linux 內存是后臺開發人員,需要深入了解的計算機資源。合理的使用內存,有助于提升機器的性能和穩定性。本文主要介紹Linux 內存組織結構
    的頭像 發表于 01-05 09:47 ?1601次閱讀

    Linux內核的物理內存組織結構詳解

    Linux內存管理子系統使用 節點(node)、區域(zone)和頁(page) 三級結構描述物理內存。
    發表于 08-21 15:35 ?543次閱讀
    <b class='flag-5'>Linux</b>內核的<b class='flag-5'>物理</b><b class='flag-5'>內存</b>組織結構詳解

    Linux內核內存規整總結

    1.前言 伙伴系統作為內核最基礎的物理內存分配器,具有高效、實現邏輯簡介等優點,其原理頁也盡可能降低內存外部碎片產生,但依然無法杜絕碎片
    的頭像 發表于 11-11 11:17 ?1277次閱讀
    <b class='flag-5'>Linux</b>內核<b class='flag-5'>內存</b>規整總結

    Linux內核內存管理之內核非連續物理內存分配

    的主要優點是避免了外部碎片,而缺點是需要修改內核頁表。顯然,非連續內存區域的大小必須是4096的倍數。Linux使用非連續物理
    的頭像 發表于 02-23 09:44 ?879次閱讀
    <b class='flag-5'>Linux</b>內核<b class='flag-5'>內存</b>管理之內核非連續<b class='flag-5'>物理</b><b class='flag-5'>內存</b>分配

    Linux內存系統: Linux 內存分配算法

    ,便于內存管理,防止內存泄露· 缺點:大量的內存碎片會使系統緩慢,內存使用率低,浪費大2) 如何避免
    發表于 08-24 07:44

    如何避免內存碎片的產生

    考試題型:單選 8 道,不定項 2 道,編程 2 道,問答 1 道考點:進程間通訊的方式,linux的基本指令(考了grep,chmod),根據代碼給出運行的結果問答題:簡述內存碎片的定義,如何
    發表于 12-21 07:50

    Linux虛擬內存物理內存的深刻分析

    內存空間的時候,只需要在虛擬內存空間分配連續空間,而不需要實際物理內存的連續空間,可以利用碎片。另外,事實上,在每個進程創建加載時,內核只
    發表于 05-31 08:00

    你知道linux kernel內存碎片防治技術?

    Linux kernel組織管理物理內存的方式是buddy system(伙伴系統),而物理內存碎片
    發表于 05-10 10:59 ?942次閱讀

    OPPO內存碎片引擎的作業

    OPPO宣傳的內存碎片引擎是個什么東西?它有何作用?針對上述問題,ColorOS官方微博特地發文科普,我們一起來看看。
    的頭像 發表于 03-15 16:20 ?3570次閱讀

    一文解析Linux內存碎片整理原理

    內存整理也是這樣,看起來很簡單,但實現起來就不那么簡單了。因為在內存整理后,需要修正進程的虛擬內存物理內存之間的映射關系。
    發表于 12-28 12:41 ?752次閱讀

    FreeRTOS內存碎片是怎么來的

    內存碎片 在看 FreeRTOS的內存分配方法之前我們先來看一下什么叫做內存碎片,看名字就知道是小塊的、
    的頭像 發表于 07-30 10:29 ?867次閱讀
    FreeRTOS<b class='flag-5'>內存</b><b class='flag-5'>碎片</b>是怎么來的

    什么是內存碎片Linux

    什么是內存碎片? 內存碎片Linux很早的時候就已經出現了,了解早期內存
    的頭像 發表于 10-08 10:12 ?701次閱讀
    什么是<b class='flag-5'>內存</b><b class='flag-5'>碎片</b><b class='flag-5'>Linux</b>

    如何解決內存碎片內存交換效率慢的問題

    內存分頁 分段的好處是能產生連續的內存空間,但是會出現大量內存碎片內存交換效率低的問題 先思考一下怎么解決這兩個問題,
    的頭像 發表于 10-09 16:57 ?998次閱讀
    如何解決<b class='flag-5'>內存</b><b class='flag-5'>碎片</b>與<b class='flag-5'>內存</b>交換效率慢的問題