无论计算机上有多少内存都是不够的,因而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小于上一次的值,则调用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。

5 参考文献

(1)《understanding the linux kernel》

(2)《professional linux kernel architecture》

linux内存回收机制的更多相关文章

  1. linux kernel内存回收机制

    转:http://www.wowotech.net/linux_kenrel/233.html linux kernel内存回收机制 作者:itrocker 发布于:2015-11-12 20:37 ...

  2. 浅谈Linux内存管理机制

    经常遇到一些刚接触Linux的新手会问内存占用怎么那么多?在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在这 ...

  3. Android 操作系统的内存回收机制(转载)

    Android 操作系统的内存回收机制(转载) Android APP 的运行环境 Android 是一款基于 Linux 内核,面向移动终端的操作系统.为适应其作为移动平台操作系统的特殊需要,谷歌对 ...

  4. 了解linux内存管理机制(转)

    今天了解了下linux内存管理机制,在这里记录下,原文在这里http://ixdba.blog.51cto.com/2895551/541355 根据自己的理解画了张图: 下面是转载的内容: 一 物理 ...

  5. linux内存管理机制

    物理内存和虚拟内存 我们知道,直接从物理内存读写数据要比从硬盘读写数据要快的多,因此,我们希望所有数据的读取和写入都在内存完成,而内存是有限的,这样就引出了物理内存与虚拟内存的概念. 物理内存就是系统 ...

  6. Android 操作系统的内存回收机制[转]

    转自:http://www.ibm.com/developerworks/cn/opensource/os-cn-android-mmry-rcycl/ Android APP 的运行环境 Andro ...

  7. 【转载】Linux 内存管理机制

    在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,主要特点是,无论物理内存有多大,Linux 都将其充份利用,将 ...

  8. Linux内存管理机制简析

    Linux内存管理机制简析 本文对Linux内存管理机制做一个简单的分析,试图让你快速理解Linux一些内存管理的概念并有效的利用一些管理方法. NUMA Linux 2.6开始支持NUMA( Non ...

  9. 【转载】浅谈Linux内存管理机制

    经常遇到一些刚接触Linux的新手会问内存占用怎么那么多? 在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在 ...

随机推荐

  1. LeetCode 84. Largest Rectangle in Histogram 单调栈应用

    LeetCode 84. Largest Rectangle in Histogram 单调栈应用 leetcode+ 循环数组,求右边第一个大的数字 求一个数组中右边第一个比他大的数(单调栈 Lee ...

  2. Objective-C-代码块Block回顾

    OC中的代码块是iOS4.0+ 和Mac OS X 10.6+ 引进的对C语言的扩展,用来实现匿名函数的特性.类似于其他语言脚本语言或者编程语言中的闭包或者是Lambda表达式,可能第一眼看上去很怪异 ...

  3. maven编译报错 -source 1.7 中不支持 lambda 表达式

    Maven项目编译失败: [ERROR] COMPILATION ERROR : [INFO] ---------------------------------------------------- ...

  4. [Angular] Use ngx-build-plus to compile Angular Elements

    We can treat Angular Element as each standlone lib and compile each Angular element spreatly. Tool w ...

  5. Discuz常见小问题-如何修改导航栏

    1 比如我要修改第一个导航栏,则在界面-导航设置,主导航,然后点击右边的编辑按钮 2 比如我把"首页"的名字改成"论坛首页",别的都不改,然后点击提交,刷新页面 ...

  6. IIS 之 Web 服务器上的 ASP.NET 进程模型设置

    配置 Microsoft Internet 信息服务 (IIS) Web 服务器上的 ASP.NET 进程模型设置. processModel 节只能在 Machine.config 文件中进行设置, ...

  7. Android 之 Android目录

    Android的目录结构如图所示: 下面来分别说说各个目录: 1.src:存放应用程序中所有的(后台)源代码,代码的源文件一般存放在相应的包下面. 2.gen:该目录下一般有BuildConfig.j ...

  8. Nginx启用ssl以及免费证书申请

    主要是这个东西,折腾了我两天,所以记录下来. 最开始是在meteor下面调用一个webservice,但是发现meteor项目的发布环境时https,所以请求的webservice也必须时webser ...

  9. HTTP Content-type整理

    文件扩展名 Content-Type(Mime-Type) 文件扩展名 Content-Type(Mime-Type) .*( 二进制流.不知道下载文件类型) application/octet-st ...

  10. MAC系统XAMPP 中 MySQL命令行client配置使用

    在PHP的学习过程中.MySQL预计是必定会接触的. MySQL的管理相信大家也会使用phpmyadmin: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv ...