本文已参与「新人创作礼」活动,一起开启掘金创作之路。
一、前言
通过《Java并发编程:虚拟内存之页面置换》,我们已经了解了页面置换
的过程以及几种常见的内存淘汰策略
。在这几种策略中,Linux使用的是LRU算法(即最近最少使用算法),本文就给大家讲解下其实现逻辑。
二、LRU的关键数据结构
在Linux中,为了实现LRU算法,它在每个内存区中都维护了两个链表,分别是active_list
(活跃链表)和inactive_list
(非活跃链表)。
active_list
用来记录内存区中经常访问
的内存页,而inactive_list
用来记录不经常访问
的内存页。页面淘汰的时候,会从非inactive_list
中选取。如下图。
除此之外,Linux还为链表中的每个内存页都设置了一个PG_referenced
的标志位,作为内存页的访问标识
。
三、内存页申请流程
Linux在申请一个新的内存页时,会将其放置到active_list
的头部,并将其PG_referenced
置为0。
四、内存页访问流程
在应用程序访问内存页时,根据内存页的不同情况,LRU会进行不同的处理:
1. 当该内存页在inactive_list
中,且PG_referenced
为0时,Linux会将该内存页的PG_referenced
置为1;
2. 当该内存页在inactive_list
中,且PG_referenced
为1时,Linux会将该内存页从inactive_list
迁移到active_list
中,并将其PG_referenced
置为0;
3. 当该内存页在active_list
中,Linux会将该内存页的PG_referenced
置为1。
五、内存页衰退流程
若一个内存页在Linux中长时间没有应用程序访问时,会触发Linux的内存页衰退过程。过程与第4节相反,具体如下:
1. 当该内存页在active_list
中,且PG_referenced
为1时,Linux会将该内存页的PG_referenced
置为0;
2. 当该内存页在active_list
中,且PG_referenced
为0时,Linux会将该内存页从active_list
迁移到inactive_list
中,并将其PG_referenced
置为0;
3. 当该内存页在inactive_list
中,Linux会将该内存页的PG_referenced
置为0。
完整的内存页访问和衰退流程,可参考下图:
六、页面淘汰处理
在进行页面淘汰
时,Linux会从inactive_list
的尾部开始,逐个遍历内存页,若该内存页的PG_referenced
为1,则跳过,并将PG_referenced
置为0,直到Linux找到一个PG_referenced
为0的内存页。
七、后言
既然看到这里了,感觉有所收获的朋友,不妨来个大大的点赞吧~~~