当前位置: 首页 > news >正文

Linux内存管理(三十一):页面回收总结

源码基于:Linux5.4

0. 前言

在 页面回收简介和 kswapd详解(1)一文中简单列举了Linux 内核中触发页面回收的机制,详细剖析了 kswapd 内核线程的初始化和唤醒过程,了解了唤醒 kswapd 内核线程的 3 种方式。

图1 是直接内存回收唤醒 kswapd 的大致流程。

在 kswapd详解(2) 一文中详细地剖析了唤醒 kswapd 内核线程后,线程核心处理函数 kswapd() 的执行过程和注意点。

图2 是唤醒kswapd 和 kswapd() 处理的大致流程。

在 shrink_node 详解 一文中详细地剖析了内存回收的核心函数 shrink_node() 的处理过程,并详细分析以节点为单位的回收函数 shrink_lruvec() 和可回收页面数量的 get_scan_count()。

图3 是shrink_node() 处理的大致流程。

 shrink_list 详解(1)一文中,继续前一篇博文 shrink_node 详解,详细地剖析了内存回收重要两个函数之一 shrink_active_list() 的处理过程和回收过程。

图4 是 shrink_active_list() 处理的大致流程。

在 shrink_list 详解(2) 一文中,继续前一篇博文 shrink_list 详解(1),详细地剖析内存回收的另一个重要函数 shrink_inactive_list() 的处理过程和内存回收过程。

图5 是shrink_inactive_list() 处理的大致流程。

本文在之前的基础上对内存回收过程进行总结,简单描述各个处理时期的注意点。

1. 唤醒kswapd的3种方式

  • 出现内存碎片时唤醒 kswapd
  • 内存严重短缺时唤醒 kswapd
  • 直接回收内存中唤醒 kswapd

第 1 种出现在快速分配内存时,如果在当前的 migrate type 中没有找到空闲内存转而去其他 migrate type 偷页面时,我们认为出现了内存外碎片化,需要根据需要唤醒 kswapd 进行内存规整。详细可以查看:buddy 系统分配器之快速分配(3)

第 2 种出现在慢速分配内存时,进入此种场景时说明内存已经出现了紧缺,通过唤醒 kswapd 来内存规整,此时并不会阻塞等待 kswapd 的完成,而是继续做其他的尝试。

第 3 种出现还是慢速分配时,此时通过规整和kswapd 后台规整还没有获取有效内存,那么会进入直接内存回收 __alloc_pages_direct_reclaim(),这里再次唤醒 kswapd,并设定等待队列 pfmemalloc_wait 等待kswapd 的完成。详细过程见下图。

图1   直接内存回收唤醒 kswapd

在 allow_direct_reclaim() 函数中等待 kswapd,直至回收完成。

2. kswapd 执行过程

图2     kswapd 执行过程

注意,

  • kswapd 初始化时设置的线程 flags;
  • kswapd_try_to_sleep() 不一定能够睡眠成功, 如果无法睡眠成功,会继续进入下一次的balance_pgdat() 函数进行页面回收;
  • scan_control.nr 基本是在 shrink_inactive_list() 中统计;
  • 内存回收之前确认是否对匿名页进行老化;
  • kswpad 内存回收的核心函数是 kswapd_shrink_node();

3. shrink_node 执行过程

图3    shrink_node 执行过程

注意,

  • sc->may_deactivate、sc->cache_trim_mode、sc->file_is_tiny 控制内存回收方向的变量都是在这里确定的;
  • inactive_is_low() 来确定 inactive list 中页面是否比较少,与active list 是保持一定的比例;

  • 内存回收是两个核心函数  shrink_lruvec() shrink_slab()

  • 回收完成后,为下一轮扫描设定的属性也是在本函数中;
  • should_continue_reclaim() 来确定是否继续回收;

4. shrink_active_list 执行过程

图4    shrink_active_list 执行过程

注意,

  • 在kswapd 内核线程回收内存之前 ,会确认是否需要对匿名页进行老化,此时也是通过shrink_active_list;
  • lru_add_drain() 会将pagevec 回归到 LRU list 中,准备回收;
  • isolate_lru_pages() 是扫描、回收页面的关键函数,将所有需要的页面进行隔离;
  • page_referenced() 用以确定页面被引用的次数,在shrink_inactive_list() 中page_check_references() 时也会调用;
  • move_pages_to_lru() 是分派页面的处理函数,将不同的page 放置到不同的list 中,没有引用的page 会被回收到 buddy 中;
  • free_unref_page_list() 用以释放页面,详细看:buddy 系统分配器之页面释放

 

5. shrink_inactive_list 执行过程

注意,

  • too_many_isolated() 针对直接内存回收,确认隔离页是否过多;
  • shrink_page_list() 是shrink_inactive_list() 核心处理函数;
  • page_check_references() 是二次机会法的核心check 函数;
  • 通过 shrink_inactive_list() 可以确认匿名页或文件页的详细回收过程;
  • 隔离时,都会给page->refcount 加1,为了防止并发释放,当然后面都会相应地减 1。详细查看 shrink_active_list() 第 2.5 节;

 

6. 页面回收总流程

其实,在 LRU 第二次机会法一文中,已经提前说明 LRU 经典算法,后面也是在这个LRU 经典算法中演变出 LRU 第二次机会法

本图是总结了LRU 算法中页面回收的流程,详细可以查看:shrink_inactive_list()一文。

相关文章:

  • 微信小程序│ 游戏开发 │连连看游戏
  • Python每日一练(牛客数据分析篇新题库)——第34天:数据清洗
  • mysql为什么使用B+树
  • 爬虫学习笔记 -- 实战某电影网(lxml库版)
  • hive on spark下row_number()问题排查
  • 最新面试题:用友OC,美团三面已挂
  • 开发者API管理神器Eolink,比postman好用
  • Mysql - 分库分表
  • 计算机毕业设计django基于python的高校奖学金管理系统(源码+系统+mysql数据库+Lw文档)
  • 软件测试的学习笔记(1)
  • c++11基础
  • 一个发誓不用Java的程序员,不得不在太空中调试Lisp
  • Android音频子系统(十一)------耳机返听(耳返)原理实现
  • 【探花交友】前后端分离、开发工具、环境搭建
  • FPGA 之 时序分析
  • JavaScript 如何正确处理 Unicode 编码问题!
  • JS中 map, filter, some, every, forEach, for in, for of 用法总结
  • [nginx文档翻译系列] 控制nginx
  • 【技术性】Search知识
  • C++回声服务器_9-epoll边缘触发模式版本服务器
  • co.js - 让异步代码同步化
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • ES6系统学习----从Apollo Client看解构赋值
  • JS实现简单的MVC模式开发小游戏
  • laravel 用artisan创建自己的模板
  • OSS Web直传 (文件图片)
  • SAP云平台里Global Account和Sub Account的关系
  • storm drpc实例
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • 构造函数(constructor)与原型链(prototype)关系
  • 机器人定位导航技术 激光SLAM与视觉SLAM谁更胜一筹?
  • 看完九篇字体系列的文章,你还觉得我是在说字体?
  • 快速构建spring-cloud+sleuth+rabbit+ zipkin+es+kibana+grafana日志跟踪平台
  • 你真的知道 == 和 equals 的区别吗?
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 判断客户端类型,Android,iOS,PC
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​第20课 在Android Native开发中加入新的C++类
  • #图像处理
  • ( 10 )MySQL中的外键
  • (007)XHTML文档之标题——h1~h6
  • (33)STM32——485实验笔记
  • (附源码)ssm教师工作量核算统计系统 毕业设计 162307
  • (一)Thymeleaf用法——Thymeleaf简介
  • (原)Matlab的svmtrain和svmclassify
  • (原創) 如何安裝Linux版本的Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (VirtualBox)
  • (原創) 物件導向與老子思想 (OO)
  • (转)mysql使用Navicat 导出和导入数据库
  • (转载)Google Chrome调试JS
  • (最简单,详细,直接上手)uniapp/vue中英文多语言切换
  • ***测试-HTTP方法