一 页回收机制

页回收机制(一)
当我们申请分配页的时候,页分配器首先尝试使用低水线分配页 。如果使用低水线分配失败,说明内存轻微不足,页分配器将会唤醒内存节点的页回收内核线程,异步回收页,然后尝试使用最低水线分配页 。如果使用最低水线分配失败,说明内存严重不足,页分配器会直接回收 。
针对不同的物理页,采用不同的回收策略:交换支持的页和存储设备支持的文件页 。
1.根据什么原则选择回收物理页
Linux内核使用LRU(LeastUsed,最近最少使用)算法选择最近最少使用的物理页 。
回收物理页的时候,如果物理页被映射到进程的虚拟地址空间,那么需要从页表中删除虚拟页到物理页的映射 。
2.LRU(最近最少使用)链表
页回收算法使用LRU算法选择回收的页 。每个内存节点的实例就有一个成员,称为LRU向量,LRU向量包含5条LRU链表 。
结构定义如下:
不活动匿名页LRU链表,用来链表不活动的匿名页,即最近访问频率低的匿名页;
活动匿名页LRU链表,用来链表活动的匿名页,即最近访问频率高的匿名页;
不活动文件页LRU链表,用来链表不活动的文件页,即最近访问频率低的文件页;
活动文件页LRU链表,用来链表活动的文件页,即最近访问频率高的文件页;
不可回收LRU链表,用来链接使用mlock锁定在内存中、不允许回收的物理页 。
3.在LRU链表中,物理页的页描述符特征:
页描述符设置标志位,表示物理页在LRU链表中;
页描述符通过成员lru加入LRU链表;
如果是交换支持的物理页,页描述符会设置标志位;
如果是活动的物理页,页描述符会设置标志位;
如果是不可回收的物理页,页描述符会设置标志位 。
每条LRU链表中的物理页按访问的时间从大到小排序,链表首部的物理页的访问时间离当前最近的,物理页从LRU链表首部加入,页回收算法从活动LRU链表的尾部取物理页回收,从活动LRU链表的尾部取物理页并且移动到不活动的LRU链表中 。
4.LRU是双向链表,内核根据页面类型(匿名和文件)与活跃性(活跃不活跃),分为5种类型的LRU链表:
5.如何确定页的活动程序?
如果是页表映射的匿名页或者文件页,根据页表项中的访问标志位确定页的活动程序 。
如果没有页表映射的文件页,进程通过系统调用read或者write访问文件,文件系统在文件的页缓存中查找文件页,为文件页的页描述符设置访问标志位就可以 。
6.反向映射
回收页表映射的匿名页或文件页时,需要从页表中删除映射,内核需要知道物理页被映射到哪些进程的虚拟地址空间,需要实现物理页到虚拟页的反向映射 。
页描述符当中和反向映射具体成员如下:
匿名页的反向映射视图如下:
7.匿名页的反向映射视图之间结构关系
8.发起页回收
【一页回收机制】申请分配页的时候,页分配器首先尝试使用低水线分配页,如果使用低水线分配失败,说明内存轻微不足,页分配器将会唤醒所有符合分配条件的内存节点的页回收线程,异步回收页,然后尝试使用最低水线分配页 。如果分配失败,说明内存严重不足,页分配器将会直接回收页 。如果直接回收页失败,那么判断是否应该重新尝试回收页 。
9.直接回收
针对备用区域列表中符合分配条件的每个内存区域,调用函数来回收内存区域所属的内存节点中的页 。回收页是以内存节点为单位执行的,函数负责回收内存节点中的页 。
直接内存回收发生在慢速分配当中,首先唤醒所有的node节点的kswap内核线程,然后才会调用st()尝试用min阈值从的zone中获取连续页框,如果失败,对的zone进行异步压缩,异步压缩之后再次调用st()尝试用min阈值从的zone中获取连续页框,如果还是失败,就会进入到直接内存回收 。