linux kernel内存回收机制

转:http://www.wowotech.net/linux_kenrel/233.htmlhtml

linux kernel内存回收机制

做者:itrocker 发布于:2015-11-12 20:37 分类:内存管理node

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

 

回收的时机android

 

 

哪些内存能够回收算法

2.1 页框的回收缓存

LRU(Least Recently Used),近期最少使用链表,是按照近期的使用状况排列的,最少使用的存在链表末尾,经过如下宏定义便可看出:函数

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

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

enum lru_list {htm

         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小于上一次的值,则调用balance_pgdat再次均衡该内存域,不然能够进行短暂休眠,休眠的时间是HZ/10,对于arm(HZ=100)来讲,休眠的时间就是1ms。

balance_pgdat均衡操做直到该内存域的zone_wartermark_ok为止。

4.2 cache_reap

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

参考文献

(1)《understanding the linux kernel》

(2)《professional linux kernel architecture》

相关文章
相关标签/搜索