首页 > linux kernel内存回收机制

linux kernel内存回收机制

http://www.wowotech.net/linux_kenrel/233.html

无论计算机上有多少内存都是不够的,因而linux kernel需要回收一些很少使用的内存页面来保证系统持续有内存使用。页面回收的方式有页回写、页交换和页丢弃三种方式:如果一个很少使用的页的后备存储器是一个块设备(例如文件映射),则可以将内存直接同步到块设备,腾出的页面可以被重用;如果页面没有后备存储器,则可以交换到特定swap分区,再次被访问时再交换回内存;如果页面的后备存储器是一个文件,但文件内容在内存不能被修改(例如可执行文件),那么在当前不需要的情况下可直接丢弃。

1 回收的时机

2 哪些内存可以回收

2.1 页框的回收

LRU(Least Recently Used),近期最少使用链表,是按照近期的使用情况排列的,最少使用的存在链表末尾,通过以下宏定义即可看出:

#define lru_to_page(_head) (list_entry((_head)->prev, struct page, lru))

每个zone有5个LRU链表用以存放各种最近使用状态的页面。

enum lru_list {

         LRU_INACTIVE_ANON = LRU_BASE,

         LRU_ACTIVE_ANON = LRU_BASE + LRU_ACTIVE,

         LRU_INACTIVE_FILE = LRU_BASE + LRU_FILE,

         LRU_ACTIVE_FILE = LRU_BASE + LRU_FILE + LRU_ACTIVE,

         LRU_UNEVICTABLE,

         NR_LRU_LISTS

};

其中INACTIVE_ANON、ACTIVE_ANON、INACTIVE_FILE、ACTIVE_FILE 4个链表中的页面是可以回收的。ANON代表匿名映射,没有后备存储器;FILE代表文件映射。

页面回收时,会优先回收INACTIVE的页面,只有当INACTIVE页面很少时,才会考虑回收ACTIVE页面。

为了评估页的活动程度,kernel引入了PG_referend和PG_active两个标志位。为什么需要两个位呢?假定只使用一个PG_active来标识页是否活动,在页被访问时,设置该位,但是何时清除呢?为此需要维护大量的内核定时器,这种方法注定是要失败的。

使用两个标志,可以实现一种更精巧的方法,其核心思想是:一个表示当前活动程度,一个表示最近是否被引用过,下图说明了基本算法。

基本上有以下步骤:

(1)如果页是活动的,设置PG_active位,并保存在ACTIVE LRU链表;反之在INACTIVE;

(2)每次访问页时,设置PG_referenced位,负责该工作的是mark_page_accessed函数;

(3)PG_referenced以及由逆向映射提供的信息用来确定页面活动程度,每次清除该位时,都会检测页面活动程度,page_referenced函数实现了该行为;

(4)再次进入mark_page_accessed。如果发现PG_referenced已被置位,意味着page_referenced没有执行检查,因而对于mark_page_accessed的调用比page_referenced更频繁,这意味着页面经常被访问。如果该页位于INACTIVE链表,将其移动到ACTIVE,此外还会设置PG_active标志位,清除PG_referenced;

(5)反向的转移也是有可能的,在页面活动程度减少时,可能连续调用两次page_referenced而中间没有mark_page_accessed。

如果对内存页的访问是稳定的,那么对page_referenced和mark_page_accessed的调用在本质上是均衡的,因而页面保持在当前LRU链表。这种方案同时确保了内存页不会再ACTIVE与INACTIVE链表间快速跳跃。

2.2 slab缓存回收

slab缓存回收相对比较灵活,所有注册到shrinker_list中的方法都会被执行。

内核默认针对每个文件系统都注册了prune_super方法,这个函数用来回收文件系统中不再使用的dentry和inode缓存;

android的lowmemorykiller机制注册了选择性杀死进程的方法,回收进程使用的内存。

3怎样回收页框

其中shrink_page_list是真正回收页面的过程





4周期性回收的频率

4.1 kswapd

kswapd是内核为每个内存node创建的内存回收线程,为什么有了紧缺回收机制还需要周期性回收呢?因为有些内存分配是不允许阻塞等待回收的,比如中断和异常处理程序中的内存分配;还有些内存分配不允许激活I/O访问的。只有少数情况的内存紧缺可以完整执行回收过程,所以利用系统空闲时间回收内存非常必要。

该函数记录了上一次均衡操作时所用的分配order,如果kswapd_max_order大于上一次的值,或者classzone_idx小于上一次的值,则调用balanc

无论计算机上有多少内存都是不够的,因而linux kernel需要回收一些很少使用的内存页面来保证系统持续有内存使用。页面回收的方式有页回写、页交换和页丢弃三种方式:如果一个很少使用的页的后备存储器是一个块设备(例如文件映射),则可以将内存直接同步到块设备,腾出的页面可以被重用;如果页面没有后备存储器,则可以交换到特定swap分区,再次被访问时再交换回内存;如果页面的后备存储器是一个文件,但文件内容在内存不能被修改(例如可执行文件),那么在当前不需要的情况下可直接丢弃。

4.2 cache_reap

cache_reap用来回收slab中的空闲对象,如果空闲对象可以还原成一个页面,则释放回buddy system。每次调用cache_reap会把所有的slab_caches遍历一遍,之后休眠2*HZ,对于arm(HZ=100)来说,周期就是20ms。

5 参考文献

(1)《understanding the linux kernel》

(2)《professional linux kernel architecture》

更多相关:

  • 更多内容,欢迎关注微信公众号:全菜工程师小辉~前言在笔者上一篇博客,详解了NIO,并总结NIO相比BIO的效率要高的三个原因,彻底搞懂NIO效率高的原理。这篇博客将针对第三个原因,进行更详细的讲解。首先澄清,零拷贝与内存直接映射并不是Java中独有的概念,并且这两个技术并不是等价的。零拷贝零拷贝是指避免在用户态(User-space)...

  • 一、预备知识—程序的内存分配  一个由c/C++编译的程序占用的内存分为以下几个部分  1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈,如果还不清楚,那么就把它想成数组,它的内存分配是连续分配的,即,所分配的内存是在一块连续的内存区域内.当我们声明变量时,那么编译器...

  • 我的爱机是一台ThinkPad T420,原装三星DDR 1333 4G内存一根,还剩一根内存位置,最近趁京东6.18促销,准备增加一根物理内存。为了确保兼容性,觉得仍然选购DDR 1333 4G内存,于是购买了金士顿这款,比如DDR3 1600的还贵。 这个安装过程完全参照该内存的网页提示进行 这里简单记录一下,以备...

  • 陪伴我多年的老本ThinkPad T420渐渐垂垂老矣, 我想更新一下可以更新的部分, 比如将2.5寸HDD更换为SSD, 将单条4G内存再增加一根, 凡此种种想法, 可能最后归结为如何获取该笔记本的硬件配置信息, 在windows下面使用鲁大师之类的检测软件, 也许很好搞定,但是在Ubuntu 14.04平台上如果办到呢? 很简单...

  • 一.内存错误出现的场景 这几天在重构ATS插件代码的过程中遇到了烦人的内存泄露问题, 周五周六连续两天通过走查代码的方法,未能看出明显的导致内存错误的代码, 同时也觉得C和C++混合编程得到一个动态库, 在一个.cpp主文件中,即用new又用malloc来动态分配内存, 可能会导致内存错误.后来网上调研和查资料发现, new和mal...

  • Window postMessage() 方法 定义和用法 postMessage() 方法用于安全地实现跨源通信。 语法 otherWindow.postMessage(message, targetOrigin, [transfer]); 参数说明otherWindow其他窗口的一个引用,比如 iframe 的 cont...

  • GitHub: https://github.com/WozHuang/mp-extend 主要目标 微信小程序官方没有提供类似vuex、redux全局状态管理的解决方案,但是在一个完整的项目中各组件的数据一致性是必须要保证,因此需要开发一个能够实现小程序全局状态管理的解决方案。 设计思路 参考omix后,我觉得其中实现全局状态管...

  • 定义全局变量的js: a.js 1 function GlobalConfig(){ 2 3 } 4 GlobalConfig.IPSSAddress="http://localhost/index/"; 5 (function(){ 6 7 })(); View Code 页面index.html里需要引用a.js 页面i...

  • 404错误页面是站长和用户都很不愿见到的页面,因为那意味着该网站不能访问。但404错误是没人能避免,如服务器出现问题,站内需要调整,收到攻击等,我们访问网站的时候,一旦遇到404提示,我们那时的感觉是相当差的,我们的用户体验马上就会下降,正因为如此,有一个良好的404页面设计来帮助我们的的访客,提示他们找不到相应的网页是那么的重要,越...

  • 代码精简使用DIV+CSS布局,页面代码精简,这一点相信对XHTML有所了解的都知道。代码精简所带来的直接好处有两点:一 是提高spider爬行效率,能在最短的时间内爬完整个页面,这样对收录质量有一定好处;二是由于能高效的爬行,就会受到spider喜欢,这样对收录数 量有一定好处。表格的嵌套问题很多网站如何推广的文章中称,搜索引擎一...