• Linux内核中的page migration和compaction机制简介


    我们知道buddy容易产生内存碎片,内核中可以通过给页面设置迁移类型以及compaction机制来预防和处理内存碎片。

    内存页主要有下面三种类型: 
    1.可移动的(movable)。用户态申请。 
    2.可回收的(reclaimable)。文件系统的cache。 
    3.不可移动(unmovable)。内核申请用。

    可移动的页面,顾名思义就是在被分配之后,还可以改变在物理内存中的位置。只要更新一下进程页表即可,进程不会感知物理页的移动。

    那么,如果不可移动的页掺杂在了可移动的页里面,它附近的页面就没办法移动凑成连续页面了。例如整个内存有 0 1 2 3 4 5 六个连续的页面,如果3是不可移动,而其他可移动的话,那么再怎么移动也只有最多三个连续的页。

    迁移类型

    内核采用给页面设置一个迁移类型(migration type)来避免这个问题: 
    我们在伙伴系统初始化时讲过,Linux启动时默认所有页都是可移动的。当内核里想申请一页,不仅申请这一页,而是一下移出很高阶的buddy内存块(例如2^9个页)设置为不可移动的,后续内核申请不可移动页就从这里申请,这样就减少了各类型页面区域之间的干扰。

    当然这块内存是动态释放和增加了,也就是说不可移动的页的范围并不是固定不变的。内核中维护了上述三种页的链表,在试图申请某个类型的页时,在期望类型的链表里申请不到页面的话,就寻求fallback类型的页面去申请,这时如果申请到内存了,就同时将这部分页面的类型改为为期望的类型(move_freepages_block()或move_freepages())。例如: 
    如果内核申请不可移动的页申请不到,就从可回收链表里拿,拿不到再从可移动链表里去拿。 
    用户空间申请的都是可移动的,直接从可移动的里面去拿,(有CMA的话,如果可移动页如果没有了,先从CMA里找,)如果找不到就从fallback链表找:先找可回收的,再找不可移动的。

    这个fallback表就是struct zone的free_area成员里的free_list[MIGRATE_TYPES]。而fallback的顺序定义如下:

    ./kernel/linux-3.0.y/mm/page_alloc.c:
    /*
     * This array describes the order lists are fallen back to when
     * the free lists for the desirable migrate type are depleted
     */
    static int fallbacks[MIGRATE_TYPES][MIGRATE_TYPES-1] = {
        [MIGRATE_UNMOVABLE]   = { MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE,   MIGRATE_RESERVE },
        [MIGRATE_RECLAIMABLE] = { MIGRATE_UNMOVABLE,   MIGRATE_MOVABLE,   MIGRATE_RESERVE },
        [MIGRATE_MOVABLE]     = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_RESERVE },
        [MIGRATE_RESERVE]     = { MIGRATE_RESERVE,     MIGRATE_RESERVE,   MIGRATE_RESERVE }, /* Never used */
    };
    
    #define MIGRATE_UNMOVABLE     0
    #define MIGRATE_RECLAIMABLE   1
    #define MIGRATE_MOVABLE       2
    #define MIGRATE_RESERVE       3
    #define MIGRATE_ISOLATE       4 /* can't allocate from here */
    #define MIGRATE_TYPES         5
    

    memory-compaction

    内核里的紧致内存机制,类似于磁盘碎片整理:把碎的页移动整合到连续的一段空间,就留出一段连续的内存了。在内核中打开CONFIG_COMPACTION就可以使用compaction功能了,要注意它只能整理可移动的页面。

    可通过下面命令主动触发内存整理:

    echo 1 > /proc/sys/vm/compact_memory
    • 1

    注意这个文件的权限是0200哦,只有root用户可以写。实际上写入的值没有意义,只作为一个触发器,内核不会判断这个值,而是直接开始对所有node所有zone尝试compaction。

    在系统内存不足时,__alloc_pages_slowpath()在尝试了kswapd间接reclaim以及借助备用zone都无果后,也会先尝试compaction能否整理出够分配order的连续内存,如果不行才进行直接reclaim的。而对于/proc/sys/vm/compact_memory触发的整理,order=-1,即尽可能多的整理。

    所以这两种方案各有其用处: 
    1. 迁移类型机制:预先将可移动的和不可移动的区分开,称为anti-fragmention。 
    2. memory-compaction:已经发生碎片了,通过整理变得不碎,称为defragmention。 
    即,迁移类型机制只是将内存按类型区分,预防碎片的发生,而不会做页面移动。memory-compation则负责在碎片发生后,对可移动页面进行整理。

    页面迁移和compaction都会有开销的,即移动页的开销,如果你频繁的申请释放导致频繁的页面迁移或频繁的整理巨页,开销就很大了。因此一定要根据实际场景。

    from: https://blog.csdn.net/jasonchen_gbd/article/details/79835655

  • 相关阅读:
    FPGA边缘检测
    Luogu P5856 【「SWTR-03」Game】
    Luogu P4707 【重返现世】
    Weight Balanced Leafy Tree
    Luogu P4311 【士兵占领】
    Luogu P4174 【[NOI2006]最大获利】
    Luogu P1646 【[国家集训队]happiness】
    Luogu P4313 【文理分科】
    Luogu P4249 【[WC2007]剪刀石头布】
    Luogu P2754 【[CTSC1999]家园 / 星际转移问题】
  • 原文地址:https://www.cnblogs.com/aspirs/p/13978966.html
Copyright © 2020-2023  润新知