Linux内存管理之页面回收


请求调页机制,只要用户态进程继续执行,他们就能获得页框,然而,请求调页没有办法强制进程释放不再使用的页框。因此,迟早所有空闲内存将被分配给进程和高速缓存,Linux内核的页面回收算法(PFRA)采取从用户进程和内核高速缓存“窃取”页框的办法不从伙伴系统的空闲块列表。

       实际上,在用完所有空闲内存之前,就必须执行页框回收算法。否则,内核很可能陷入一种内存请求的僵局中,并导致系统崩溃。也就是说,要释放一个页框,内核就必须把页框的数据写入磁盘;但是,为了完成这一操作,内核却要请求另一个页框(例如,为I/O数据传送分配缓冲区首部)。因为不存在空闲页框,因此,不可能释放页框。

       页框算法的目标之一就是保存最少的空闲页框并使内核可以安全地从“内存紧缺”的情形中恢复过来。

选择目标页

       PFRA的目标就是获得页框并使之空闲。PFRA按照页框所含内容,以不同的方式处理页框。我们将他们区分成:不可回收页、可交换页、可同步页和可丢弃页:

页类型

说明

回收操作

不可回收页

空闲页(包含子伙伴系统列表中)

保留页(PG_reserved标志置位)

内核动态分配页

进程内核态堆栈页

临时锁定页(PG_locked标志置位)

内存锁定页(在先行区中且VM_LOCKED标志置位)

不允许也无需回收

可回收页

用户太地址空间的匿名页

Tmpfs文件系统的映射页(如IPC共享内存的页)

 

将页的内容保存在交换区

可同步页

用户态地址空间的映射页

存有磁盘文件数据且在页高速缓存中的页

块设备缓冲区页

某些磁盘高速缓存的页(如索引节点高速缓存)

必要时,与磁盘镜像同步这些页

可丢弃页

内存高速缓存中的未使用页(如slab分配器高速缓存)

目录想高速缓存的未使用页

无需操作

 

进行页面回收的时机

        Linux 操作系统使用如下这两种机制检查系统内存的使用情况,从而确定可用的内存是否太少从而需要进行页面回收。

    • 周期性的检查:这是由后台运行的守护进程 kswapd 完成的。该进程定期检查当前系统的内存使用情况,当发现系统内空闲的物理页面数目少于特定的阈值时,该进程就会发起页面回收的操作。
    • “内存严重不足”事件的触发:在某些情况下,比如,操作系统忽然需要通过伙伴系统为用户进程分配一大块内存,或者需要创建一个很大的缓冲区,而当时系统中的内存没有办法提供足够多的物理内存以满足这种内存请求,这时候,操作系统就必须尽快进行页面回收操作,以便释放出一些内存空间从而满足上述的内存请求。这种页面回收方式也被称作“直接页面回收”。
    • 睡眠回收,在进入suspend-to-disk状态时,内核必须释放内存。

       如果操作系统在进行了内存回收操作之后仍然无法回收到足够多的页面以满足上述内存要求,那么操作系统只有最后一个选择,那就是使用 OOM( out of memory )killer,它从系统中挑选一个最合适的进程杀死它,并释放该进程所占用的所有页面。

       上面介绍的内存回收机制主要依赖于三个字段:pages_min,pages_low 以及 pages_high。每个内存区域( zone )都在其区域描述符中定义了这样三个字段,这三个字段的具体含义如下表 所示。

字段含义

名称

字段描述

pages_min

区域的预留页面数目,如果空闲物理页面的数目低于 pages_min,那么系统的压力会比较大,此时,内存区域中急需空闲的物理页面,页面回收的需求非常紧迫。

pages_low

控制进行页面回收的最小阈值,如果空闲物理页面的数目低于 pages_low,那么操作系统内核会开始进行页面回收。

pages_high

控制进行页面回收的最大阈值,如果空闲物理页面的数目多于 pages_high,则内存区域的状态是理想的。

 

PFRA设计

设计总则

1.       首先释放“无害”页,即必须线回收没有被任何进程使用的磁盘与内存高速缓存中的页;

2.       将用户态进程和所有页定为可回首页,FPRA必须能够窃得人任何用户态进程页,包括匿名页。这样,睡眠较长时间的进程将逐渐失去所有页;

3.       同时取消引用一个共享页的所有页表项的映射,就可以回收该共享页;

4.       只回收“未用”页,使用LRU算法。Linux使用每个页表项中的访问标志位,在页被访问时,该标志位由银奖自动置位;而且,页年龄由页描述符在链表(两个不同的链表之一)中的位置来表示。

因此,页框回收算法是集中启发式方法的混合:

1.  谨慎选择检查高速缓存的顺序;

2.  基于页年龄的变化排序;

3.  区别对待不同状态的页;

反向映射

        PFRA的目标之一是能释放共享页框。为达到这个目地。Linux内核能够快速定为指向同一页框的所有页表项。这个过程就叫做反向映射。Linux 操作系统为物理页面建立一个链表,用于指向引用了该物理页面的所有页表项。

基本思想如下图:

       Linux采用“面向对象的反向映射”技术。实际上,对任何可回收的用户态页,内核保留系统中该页所在所有现行区(“对象”)的反向链接,每个线性区描述符( vm_area_struct 结构)存放一个指针指向一个内存描述符( mm_struct 结构),而该内存描述符又包含一个指针指向一个页全局目录(PGD)。因此,这些反向链接使得PFRA能够检索引用某页的所有页表项。因为线性区描述符比页描述符少,所以更新共享页的反向链接就比较省时间。下面是具体的实现:

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 下一页

相关内容