文章目录
对于linux内存回收来说,lru链表是关键,因为内存回收的整个过程都是处理lru链表的收缩。lru链表的作用就是对进行页排序,将应该回收的页放在链表尾部,最不该回收的页放在链表头部;内存回收主要是将lru链表中最近很少访问的尾部页框内容从内存转储到磁盘中,然后将转储后的页框释放到伙伴系统作为空闲内存使用。
LRU机制与linux内存回收
linux 内存回收引入 LRU链表的原因
linux长时间运行后,内存会出现吃紧的状况,空闲内存慢慢变少。这个时候linux内存管理系统就会通过内存回收机制来回收进程正在使用的匿名页和文件页。回收这些页框时,如果内存管理系统不进行挑选,很可能刚刚回收释放的页框很快会被重新用到,这样又必须将转储到磁盘的内容再次写入内存,这样就会造成页抖动(page thrashing)或者缓存抖动(cache thrashing),极大降低系统性能。
那么在内存回收时如何合理地选择回收的页框,是减缓系统页抖动,提高系统性能的关键。通常为了防止刚回收的页框不会很快再次被内存使用,那么内存回收选则的页框应该是那些最近不被使用,不活跃的页框。
linux内存管理系统是通过引入LRU算法来对回收的页框进行筛选。主要是将分配给进程的页框储在对应的LRU链表中,通过LRU算法获取到最近不活跃的页框,并将这些页框转交给内存回收系统进行释放处理。
linux通过LRU链表筛选出理想的回收页框原理
linux内存管理系统如何通过引入LRU链表筛选出不活跃的页框?
linux维护了2个双向的lru链链表:
- active_list:该链表中包含的是最近使用的页面
- inactive_list:该链表中包含的是最近不使用的页面
页框中struct page中的lru指向了其所在lru链表中前后页框的指针,且struct page的flags中使用了PG_referenced和PG_active两个标志位来标识页面的活跃程度。
- PG_active标志位指示了该页块因该在哪个lru链表,PG_active标志位为1在activ_list链表,为0在inactive_list
- PG_referenced标志位指示了该页框是否被使用;若页框被访问,mark_page_accessed()会检测该page的PG_referenced位,PG_referenced位为0,将其置为1.
void mark_page_accessed(struct page *page)
{
...
if (!PageActive(page) && PageReferenced(page)) {
activate_page(page);
}
else if (!PageReferenced(page)) {
SetPageReferenced(page);
}
...
}
active_list和inactive_list都是采用先进先出(FIFO)的方式。新的页从链表头加入,链表中间的元素逐渐向尾部移动。而内存回收时,总是选择inactive_list链表的尾部进行回收。两个链表中页的移动情况如下:
- 在inactive_list上PG_referenced为1的页在回收前被再次访问到,也就是说它在inactive_list中被访问了2次,mark_page_accessed()就会调用activate_page()将其置换到active_list的头部,同时将其PG_active位置1,PG_referenced位清0(两个PG_referenced才换来一个PG_active)
- 在inactive_list中的页在移动到尾部时,若PG_referenced位为0,则内存回收机制被触发时,该页框将会被回收
- 在inactive_list中的页在移动到链表尾部,若PG_referenced位为1,该页是否被回收,要依赖与linux内核的机制。(在内存回收这一块,很多事后是根据经

本文介绍了Linux内核中LRU机制与内存回收。Linux内存回收引入LRU链表,通过active_list和inactive_list筛选不活跃页框。为解决多核环境锁竞争问题,提出LRU缓存机制。内核将LRU链表拆分为5个,优先回收文件页,还介绍了链表内核代码实现。

1134

被折叠的 条评论
为什么被折叠?



