本文主要介绍了一些page reclaim机制中的基本概念。这份文档其实也可以看成阅读ULK第17章第一小节的一个读书笔记。虽然ULK已经读了很多遍,不过每一遍还是觉得有收获。Linux内核虽然不断在演进,但是页面回收的基本概念是不变的,所以ULK仍然值得内核发烧友仔细品味。

一、什么是page frame reclaiming?

在用户进程的内存使用上,Linux内核并没有严格的限制,其实思路是:当系统负荷小的时候,内存都是位于各种cache中,以便提高性能。当系统负荷重(进程数目非常多)的时候,cache中的内存被收回,然后用于进程地址空间的创建和映射。在这样思路的指导下,一开始,内核大手大脚,一直从伙伴系统的free list上分配page frame给用户进程或者各种kernel cache使用,但是系统内存终归是有限的,当伙伴系统的空闲内存下降到一定的水位的时候,系统会从用户进程或者kernel cache中回收page frame到伙伴系统,以便满足新的内存分配的需求,这个过程就是page frame reclaiming。一言以蔽之,page frame reclaiming就是保证系统的空闲内存在一个指定的水位之上。

二、什么时候启动page frame reclaiming?

能不能等到空闲内存用尽之后才启动page frame reclaiming呢?不行,因为在page frame reclaiming的过程中也会消耗内存(例如在页面回收过程中,我们可能会将page frame的数据交换到磁盘,因此需要分配buffer head数据结构,完成IO操作),因此我们必须在伙伴系统中保持一定的水位,以便让page frame reclaiming机制正常工作,以便回收更多的内存,让系统运转下去,否则系统会crash掉。

三、哪些场景可以触发page frame reclaiming?

当分配内存失败的时候触发页面回收是最直观的想法,然而内核的场景没有那么简单,例如在中断上下文中分配内存,这时候我们不能触发page frame reclaiming,因为这时候我们不能阻塞当前进程。此外,有些内存分配的场景是发生在持锁之后(以便对某些资源进行排他性的访问),这时候,我们也不能激活IO操作,进行内存回收。

因此,总结起来,内核在内存回收的思路就是:系统在分配内存的时候就进行检查,如果有需要就唤醒kswapd,让系统的空闲内存的数量保持在一个水平之上,以免将自己逼入绝境。如果没有办法,的确进入了绝境(分配内存失败),那么就直接触发页面回收。具体的场景包括:

1、synchronous page reclaim,即当遭遇分配内存失败的时候,一言不合,然后直接调用page frame reclaiming进行回收。例如:在分配page buffer的时候(alloc_page_buffers),如果分配不成功,直接调用free_more_memory进行内存回收。或者在调用__alloc_pages的时候,如果分配不成功,直接调用try_to_free_pages进行内存回收。当然,其实free_more_memory也是调用try_to_free_pages来实现页面回收的。

2、Suspend to disk(Hibernation)的场景。系统hibernate的时候需要大量内存,这时候会调用shrink_all_memory来回收指定数目的page frame。

3、kswapd场景。Kswapd是一个专门用来进行页面回收的内核线程。

4、slab内存分配器会定时的queue work到system_wq上去,从而会周期性的调用cache_reap来回收slab上的空闲内存。

四、页面回收的策略为何?

首先我们需要对page frame进行分类,主要分成4类:

1、 没有办法回收的page frame。包括空闲页面(已经在free list上面,也就不需要劳驾page frame reclaim机制了)、保留页面(设定了PG_reserved,例如内核正文段、数据段等等)、内核动态分配的page frame、用户进程的内核栈上的page frame、临时性的被锁定的page frame(即设定了PG_locked flag,例如在进行磁盘IO的时候)、mlocked page frame(有VM_LOCKED标识的VMA)

2、 可以交换到磁盘的page frame(swappable)。用户空间的匿名映射页面(用户进程堆和栈上的page frame)、tmpfs的page frame。

3、 可以同步到磁盘的page frame(syncable)。用户空间的文件映射(file mapped)页面,page cache中的page frame(其内容会对应到某个磁盘文件),block device的buffered cache、disk cache中的page frame(例如inode cache)

4、 可以直接释放的page frame。各种内存cache(例如 slab内存分配器)中还没有使用的那些page frame、没有使用的dentry cache。

上面的第二类和第三类有些类似, 其page frame都有后备文件或者磁盘,不过我们可以这么区分。Swappable的page frame,其数据的最终地点就是内存,其后备文件或者磁盘只是为了延伸内存的容量。Syncable的page frame,其数据的最终地点就是磁盘,内存只不过是为了加快速度而已。因此,当回收swappable的页面的时候,需要将page frame的数据保存到后备的磁盘或者文件。而当回收syncable页面的时候,要看page frame是否是dirty的,如果dirty,则需要磁盘操作,否则可以直接回收。

圈定进行页面回收的那些候选page frame很容易(即上面的2、3、4类型的page frame),但是怎么考虑页面回收的先后顺序呢?Linux内核设定的基本规则如下:

1、 尽量不要修改page table。例如回收各种没有使用的内核cache的时候,我们直接回收,根本不需要修改页表项。而用户空间进程的页面回收往往涉及将对应的pte条目修改为无效状态。

2、 除非调用mlock将page锁定,否则所有的用户空间对应的page frame都应该可以被回收。

3、 如果一个page frame被多个进程共享,那么我们需要清除所有的pte entry,之后才能回收该页面。

4、 不要回收那些最近使用(访问)过的page frame,或者说优先回收那些最近没有访问的page frame。

5、 尽量先回收那些不需要磁盘IO操作的page frame。

Linux页面回收概述的更多相关文章

  1. Linux内核入门到放弃-页面回收和页交换-《深入Linux内核架构》笔记

    概述 可换出页 只有少量几种页可以换出到交换区,对其他页来说,换出到块设备上与之对应的后备存储器即可,如下所述. 类别为 MAP_ANONYMOUS 的页,没有关联到文件,例如,这可能是进程的栈或是使 ...

  2. Linux内存管理之页面回收【转】

    转自:http://blog.csdn.net/bullbat/article/details/7311205 请求调页机制,只要用户态进程继续执行,他们就能获得页框,然而,请求调页没有办法强制进程释 ...

  3. linux 设备驱动概述

    linux 设备驱动概述 目前,Linux软件工程师大致可分为两个层次: (1)Linux应用软件工程师(Application Software Engineer):       主要利用C库函数和 ...

  4. linux内存回收机制

    无论计算机上有多少内存都是不够的,因而linux kernel需要回收一些很少使用的内存页面来保证系统持续有内存使用.页面回收的方式有页回写.页交换和页丢弃三种方式:如果一个很少使用的页的后备存储器是 ...

  5. 自学linux——9.Linux的权限概述

    Linux的权限概述 一.      权限概述 1.权限介绍 在多用户(可以不同时)计算机系统的管理中,权限是指某个特定的用户具有特定的系统资源使用权力,像是文件夹.特定系统指令的使用或存储量的限制 ...

  6. JVM垃圾回收概述

    垃圾回收概述 什么是垃圾 什么是垃圾( Garbage) 呢? 垃圾是指在运行程序中没有任何指针指向的对象,这个对象就是需要被回收的垃圾. 如果不及时对内存中的垃圾进行清理,那么,这些垃圾对象所占的内 ...

  7. 自动驾驶QNX,Linux,Autosar概述

    自动驾驶QNX,Linux,Autosar概述 QNX是一个分布式.嵌入式.可规模扩展的实时操作系统.遵循POSIX.1 (程序接口)和POSIX.2 (Shell和工具).部分遵循POSIX.1b( ...

  8. linux内核——1.概述

    1.结构 linux中,我们把操作系统分为内核空间和用户空间.用户通过用户空间与操作系统打交道.用户要通过系统调用访问内核空间.下图为Linux体系结构,shell应该为在最顶层. 系统调用,下面链接 ...

  9. Linux进程实践(1) --Linux进程编程概述

    进程 VS. 程序 什么是程序? 程序是完成特定任务的一系列指令集合. 什么是进程? [1]从用户的角度来看:进程是程序的一次执行过程 [2]从操作系统的核心来看:进程是操作系统分配的内存.CPU时间 ...

随机推荐

  1. Byedance AI Camp-笔试题目

    最小m段和问题:给定n个整数组成的序列,现在要求将序列分割为m段,每段子序列中的数在原序列中连续排列.如何分割才能使这m段子序列的和的最大值达到最小? Input 第一行输入一个整数t,代表有t组测试 ...

  2. jQuery实现新浪微博自动底部加载的方法

    jQuery ScrollPagination plugin 是一个jQuery 实现的支持无限滚动加载数据的插件. 地址:http://andersonferminiano.com/jquerysc ...

  3. java读取某个目录是否有新增文件(轮询)

    使用 commons-io 中的文件监控 jar包: package org.demo.file; import java.util.concurrent.TimeUnit; import org.a ...

  4. 网络结构设计——负载均衡之LVS学习笔记(二)

    LVS按个人理解的说就是将一台Linux服务器当作路由器等功能的技术.LVS---Linux虚拟服务器. LVS实现了三种IP负载均衡技术VS/NAT.VS/TUN.VS/DR. 今天简单分享一下我在 ...

  5. Error Lookup工具

    GetLastError()获取到的错误代码,可以通过VS2013自带的Error Lookup工具来查询错误的描述.

  6. [Javascript] Using map() function instead of for loop

    As an example, if Jason was riding the roller coaster (and when isn’t he), your goal would be to cha ...

  7. windows 用户变量和系统变量的差别

    点击"我的电脑→属性→高级系统设置"标签的"环境变量"button,出现"环境变量"对话框,假设当前是以Administrator登录系统的 ...

  8. CSDN-Code平台公钥设置

    近期,把自己的2个比較重要的项目,中国象棋-个人官网,放到了CSDN的Code平台.当然,眼下是私有的,有开源部分项目的计划. 开发过程中,我是使用Windows平台的,工作和娱乐两不误. 近期,想要 ...

  9. LoadRunner录制:集合点

    背景 LoadRunner 执行过程中,有的user 跑的快,有的跑的慢.就导致user1可能还在执行 登录操作呢,user2都已经开始执行查询操作了. 但是在进行负载测试时 ,我们又需要让很多用户同 ...

  10. adb(Android Debug Bridge)(一)

    上一篇介绍的am,pm命令都是基于adb shell下的命令.这节来详细介绍下adb命令. Android Debug Bridge(adb)是一个让你跟模拟器或者android设备通信的多功能命令. ...