16. 页框回收 2010-02-28 22:56 591人阅读 评论(0) 收藏
系统负载较低时,RAM大部分由磁盘高速缓存占用。负载增加时,RAM大部分则由进程页占用,高速缓存会缩小从而给进程让出空间,之前的所有内存管理并未释放页。Linux内核的页框回收算法(PFRA)采用从用户态进程和内核缓存“窃取”页框以补充伙伴系统空闲块列表。
回收的第一步是选择目标页,按页框可分为不可回收页,可交换页,可同步页,可丢弃页。对于页框回收算法来说,可交换页与可同步页是目标。前者可将内容保存在交换区以释放,可同步页则可直接将缓存写到磁盘。可交换页包括用户态的匿名页即用户态的堆与栈,及IPC共享内存的页等,可同步页包括用户态的映射页(文件映射内存)、页高速缓存、块缓冲、磁盘的inode缓存等。所以PFRA选定目标粗略为磁盘、内存高速缓存、用户态地址空间,但回收算法则很少有理论支撑,是相当经验性的。LRU算法的主要思想是以计数存放Ram中每页的年龄,有的CPU支持这种功能,但80x86不支持。为释放页框中的共享页框,PFRA要能迅速找到指向同一页框的所有页表项,这个过程叫反射映射。实现方法可在页描述符中加入字段,联系到对应的所有页表项,但这样开销太大。Linux采用“面向对象的反射映射”,对于任何可回收的用户态页,内核保留页到所属线性区的反向链接。线性区描述符又有指针指向内存描述符,内存描述符又有指针指向页全局目录。这是个由内到外由小到大的过程,内核会先看页描述符的__mapcount与mapping字段,前者说明页框共享否,后者说明交换高速缓存,若非空则看最低位。1则是匿名页,0则映射页。若匿名页,反向映射可直接将页框所在匿名线性区存于双向循环链表。若映射页,则不行,因为它的数量可能很大,如C库代码的页可能有许多映射。Linux2.6引入优先搜索树(PST)来检索。
页框回收算法的核心数据结构是页的活动链表与非活动链表,它们称为LRU链表。前者放最近访问过的页,后者存放有段时间未访问过的页。它俩存在zone描述符的active_list与inactive_list中,并在页描述符中有字段指出在哪个链表或不在LRU链表。因为页要来回移动于两链表间,则光两个状态可能就不够。但并未引入新状态而是不在单独访问中就改变状态,实现移动的函数也不可太强,否则过多页移至非活动则要影响系统性能,过懒时则PFRA回收不力。PFRA倾向于先压缩页高速缓存,而非用户态进程的页。对进程页,可通过设交换值设定。对于目录项与inode高速缓存,会先判断它们是否可压缩,即判断从LRU收回与压缩的代价,再作出权衡。
PFRA有两种周期回收机制:kswapd内核线程从LRU链表中回收页,cache_reap则从slab分配器中回收未用slab,前者在分配内存时若阈值低于某值被激活。
极端时,交换区满,且磁盘高速缓存已被压缩,内存耗尽,此时,PFRA使用OOM(out of memory)删除程序,它选择一个进程强行删除它并释放页框。
Linux VM子系统代码太复杂,尤以PFRA,有时它会产生把某页换出再换入这种叫“交换失效”的情况,解决方法是用交换标记。交换是为非映射页在磁盘上提供备份。交换子系统要完成建立交换区、分配页槽,换入换出等,它是页框回收的最高级特性。交换区可实现于硬盘分区也可以使用文件。每交换区由一组页框组成,每页框包括一个被换出的页。第一页框(标号0)存放交换区信息,每个交换区由一或多个子交换区组成,每子区对应在磁盘上物理相邻的页,交换区由数据结构swap_info_struct描述符描述。Swap_map字段指向计数器数组,指出共享换出页的进程数。为找到换出页,引入换出页标识符,它指出了页槽索引、区号及有一位与present对应,80x86上页槽索引为24位,所以交换区可有64G,换出一页后,换出页标志符会放在页表项备查。换出时要找空闲页槽,Linux一般从上次已分配的页槽开始找。为了应付可能的多重换入及同时换入换出的情况,交换高速缓存被引入,它是个临时区域,存放正在换入或换出的匿名页描述符。换入一般在缺页异常处理中触发。
版权声明:本文为博主原创文章,未经博主允许不得转载。