linux 内存回收lru算法代码注释1

本文为旧的lru算法,多代lru算法与旧算法的区别可稳步:linux内存回收mglru算法-CSDN博客

1.shrink_node_memcgs

node_reclaim->__node_reclaim->shrink_node,这里调用shrink_node_memcgs回收后,要判断下是否分配内存速度比回收速度快太多,这种情况可能会尝试停一段时间等回收完成(reclaim_throttle),然后再看是否需要继续回收(should_continue_reclaim)。实际入口shrink_node_memcgs如下:

shrink_node_memcgs():
for each memory control group:/*** 按照指定的预留min/low内存,从上层节点瓜分实际分到的min/low预留内存大小。* 具体见:https://blog.csdn.net/qq_37517281/article/details/134466144*/mem_cgroup_calculate_protection()if (mem_cgroup_below_min(target_memcg, memcg)) {// 本group分配的未达到min预留内存,尝试下个groupcontinue;} else if (mem_cgroup_below_low(target_memcg, memcg)) {// 如果指定不对未达到low限制的group回收内存,则只标记下skipif (!sc->memcg_low_reclaim) {sc->memcg_low_skipped = 1;continue;}}// 尝试回收页与slabshrink_lruvec();shrink_slab();/*** 计算些时回收压力: 回归页/扫描页数×100* 大于60是中等压力,大于95是严重压力。*/vmpressure();

2.shrink_lruvec

shrink_lruvec 中会计算本次要扫描的页数,然后触发实际的扫描和页回收(shrink_list):实现如下:

shrink_lruvec():// 计算要扫描页数get_scan_count(lruvec, sc, nr);while 未扫描足够的页数且文件页或匿名页数量都不是0:for 2个 active lru list(file and anon):// 如果指定了may_deactivate,则尝试将部分hot 页移至cold 链表中shrink_active_list();for 2个 inactive lru list(file and anon):shrink_inactive_list();// 如果匿名页的cold页少,尝试deactivate 一些老的hot匿名页。shrink_active_list();

3.get_scan_count

 scan 四个lru链表页数计算方法如下(get_scan_count):

get_scan_count():/*** 先判断回收文件页还是匿名页,只扫描文件页的情况:* a.没有swap空间* b.一个cgroup的memory.swappness为0(swapness表示对换出匿名页与重加载文件页的cost的加权,cost 指scan过程中发现的不可换出的页数+换出页×32)* c.指定了回收缓存文件页(cache_trim_mode)* 只扫描匿名页的情况:* a.文件页很少* 同时回收文件页和匿名页的情况:* a.即将oom时,这时的priority为0(后面扫描时,对所有可扫描页的扫描比例为priority分之一)* 其它情况下,会计算文件页与匿名页扫描比例,比例的原始值控制在1/3 - 2/3之间* (当anon_cost为0时,ap 与 fp 的未加权的原始比是1:2),* 取决于扫描时的cost(scan过程中发现的不可换出的页数+换出页×32)* 乘上一个换出匿名页与加载文件页的io cost比(swapness/200)**/total_cost = sc->anon_cost + sc->file_cost;anon_cost = total_cost + sc->anon_cost;file_cost = total_cost + sc->file_cost;total_cost = anon_cost + file_cost;ap = swappiness * (total_cost + 1);ap /= anon_cost + 1;fp = (200 - swappiness) * (total_cost + 1);fp /= file_cost + 1;fraction[0] = ap;fraction[1] = fp;denominator = ap + fp;// 计算 4 个 lru list (active/inactive × anon/file)扫描数量: if (!sc->memcg_low_reclaim && low > min) {protection = low;sc->memcg_low_skipped = 1;} else {protection = min;}// scan = lru页数-组内预留页数scan = lruvec_size - lruvec_size * protection / (cgroup_size + 1);// priority 默认为 12scan >>= sc->priority;scan = mem_cgroup_online(memcg) ?div64_u64(scan * fraction[file], denominator) :DIV64_U64_ROUND_UP(scan * fraction[file],denominator);

4.shrink_active_list

将active 页移至inactive页的方法(shrink_active_list):

shrink_active_list():/*** 处理一批本cpu上的页状态转换请求(cpu_fbatches),和对页标记可否回收的请求(mlock_fbatch)* 1、新访问的页和最新分配的页会记在fbatches->lru_add上,处理函数是 lru_add_fn。* 2、writeback的页放在lru_rotate.fbatch,处理函数是 lru_move_tail_fn,将其放在inactive 的tail上,等待回收(页回收是从tail开始的)* 3、madvice 为don't need的页,或是free了的设备页、文件页,放在cpu_fbatches.lru_deactivate_file,处理函数是 lru_deactivate_file_fn * 会将dirty/writeback/clean页放inactive的head上* 4、匿名页比如内核自己使用并释放的页,放在 cpu_fbatches.lru_deactivate,处理函数是 lru_deactivate_fn 将页框放在 active 的head上* 5、huge page 是lazyfree的,放在cpu_fbatches.lru_lazyfree上,处理函数是 lru_lazyfree_fn 会将页当成clean页,放在inactive 的头上。*/lru_add_drain();// 从后向前扫描,跳过高于指定zone的区和cma的区,从这中间的区找可以unmap的页框,或未map的页框isolate_lru_folios();for 每个扫描出的页框:// 判断这个页框没有mlock的vma,且它的mapping也没有标记unevictableif (unlikely(!folio_evictable(folio))) {folio_putback_lru(folio);continue;}// 如果buffer的总数太多,且这个页框中有buffer,则尝试解除映射if (unlikely(buffer_heads_over_limit)) {if (folio_test_private(folio) && folio_trylock(folio)) {if (folio_test_private(folio))filemap_release_folio(folio, 0);folio_unlock(folio);}}// 尝试把code文件页加入active队列,把其它页加入inactive队列list_add(&folio->lru, &l_inactive);// 给evictable的页引用减1,引用不为0的加入到lru的inactive或active的lru中。引用为0则尝试释放,对页框中有超过1页的情况,调用页框绑定的destroy;对于只有一页的情况,攒起来在后面两个函数内释放。move_folios_to_lru()// 释放只有一页的页框mem_cgroup_uncharge_list();free_unref_page_list();

5.shrink_inactive_list

shrink_inactive_list():// 处理一批本cpu上的页状态转换请求(cpu_fbatches),和对页标记可否回收的请求(mlock_fbatch)lru_add_drain();// 从lru中切出要扫描的页isolate_lru_folios();// 将一些页换出shrink_folio_list();// 将没有迁移成功、没有换出成功、没有写回文件的页重新加回原lru链表,并将ref减1move_folios_to_lru();// 统计costlru_note_cost(lruvec, file, stat.nr_pageout, nr_scanned - nr_reclaimed);// 将ref减1后为0的页框释放掉mem_cgroup_uncharge_list(&folio_list);free_unref_page_list(&folio_list);

6.shrink_folio_list

shrink_inactive_list会将部分页回收、送入swap区,或迁移到其它numa node上。具体实现如下:

shrink_folio_list():
if (folio_test_writeback(folio)) {/*** 如果已经标记了writeback和reclasim,说明它在等io,* 这时需要activate它并继续scan来找其它inactive list上可以回收的folio* (如果是swap区的,将swapcache相关项清理掉)*/if (current_is_kswapd() &&folio_test_reclaim(folio) &&test_bit(PGDAT_WRITEBACK, &pgdat->flags)) {stat->nr_immediate += nr_pages;goto activate_locked;} else if (writeback_throttling_sane(sc) ||!folio_test_reclaim(folio) ||!may_enter_fs(folio, sc->gfp_mask)) {/*** 如果本次扫描不没指定可访问文件系统(__GFP_FS or __GFP_IO),* 且这个页还没标记可回收,就标记一下这个页框可回收并继续scan* 可能在下一次扫描时回收*/folio_set_reclaim(folio);stat->nr_writeback += nr_pages;goto activate_locked;} else {/*** 如果已经标记了页框回收,则已经扫描一遍了,只能等writeback结束*/folio_unlock(folio);folio_wait_writeback(folio);/* then go back and try same folio again */list_add_tail(&folio->lru, folio_list);continue;}
}
folio_check_references();
// 如果没有引用,则考虑可否直接回收,先尝试迁移到最近距离的下一个node(demote_folio_list,下一个node记录在全局的node_demotion中)
if (do_demote_pass &&(thp_migration_supported() || !folio_test_large(folio))) {list_add(&folio->lru, &demote_folios);folio_unlock(folio);continue;
}
// 看是否是匿名可进swap区的页(有页面映射且没有人为它建过swapcache),为它建立swapcache项
if (folio_test_anon(folio) && folio_test_swapbacked(folio)) {if (!folio_test_swapcache(folio)) {// 添加一个swap区的映射entryadd_to_swap();}
}
// 对于文件页和没有swapcache的匿名页,需要给它解除页表映射项
if (folio_mapped(folio)) {try_to_unmap(folio, flags);
}
// 对于dirty的页,只有kswapd进程可以直接回收,其它进程只能柡注reclaim,以防止stack overflow
if (folio_test_dirty(folio)) {// kswapd进程来回收了,需要把tlb刷下去try_to_unmap_flush_dirty();pageout();
}
// 如果这个页框还有buffer,尝试解除clean的和没有映射的buffer
if (folio_has_private(folio)) {filemap_release_folio(folio, sc->gfp_mask)
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/179415.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

对坐标的曲面积分@第二类曲面积分

文章目录 abstract曲面基本概念双侧曲面有向曲面曲面区域投影平面区域投影 对坐标的曲面积分流向曲面一侧的流量简单情形 一般情形小结 对坐标的曲面积分其他定义第二类曲面积分的存在性并写和简写流量用第二类曲面积分描述 性质对坐标的曲面积分的计算公式的其他形式应用例例 …

使用webdriver-manager自动下载浏览器驱动(python)

使用webdriver-manager自动下载浏览器驱动,再也不用担心webdriver版本问题 文章目录 01 简介 02 安装webdriver_manager 03 ChromeDriver 3.1 Selenium 3 用法 3.2 Selenium 4 用法 04 EdgeChromiumDriver 4.1 Selenium 3 用法 4.2 Selenium 4 用法 05 GeckoDrive…

MySQL进阶知识:二

目录 视图 基本语法 视图的更新 视图的作用 存储过程 介绍 存储过程基本语法 存储过程的变量 系统变量 用户自定义变量 局部变量 存储过程的判断逻辑 存储过程的参数 存储过程中的流程控制 存储过程中的循环 while的基本语法 repeat的基本语法 loop的基本语法…

金山办公前端二面

1. react 和 vue的区别 还有jquery? (1) jquery 和 vue、react 的区别: vue 和 react : 数据和视图分离 以数据驱动视图,只关心数据变化 dom 操作被封装(数据驱动) jquery:依靠 do…

【问题解决!】OSError: [WinError 1455] 页面文件太小,无法完成操作。Error loading “c:\Anaconda3\lib

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 问题描述问题原因二、解决方法 问题描述 在使用pytorch跑深度学习的时候报错OSError: [WinError 1455] 页面文件太小,无法完成操作。Error loading “c…

系列七、事务

一、事务 1.1、概述 事务是数据库操作的基本单元,它是指逻辑上的一组操作,要么都成功,要么都失败。典型场景:转账,例如Jack给Rose转账1000元,转账成功:Jack账户的余额少1000元,Rose…

【C++】enum枚举与强类型枚举

enum 文章目录 enumenum枚举枚举变量强类型枚举 enum枚举 C的enum工具提供了一种创建符号常量的方式,这种方式可以替代const 枚举类型定义用关键字enum标识 enum 标识符 {枚举数据表 };枚举数据表的值都是整数。第一个枚举成员的默认值为整型的0&…

人脸识别经典网络-MTCNN(含Python源码实现)

人脸检测-mtcnn 本文参加新星计划人工智能赛道:https://bbs.csdn.net/topics/613989052 文章目录 人脸检测-mtcnn1. 人脸检测1.1 人脸检测概述1.2 人脸检测的难点1.3 人脸检测的应用场景 2. mtcnn2.1 mtcnn概述2.2 mtcnn的网络结构2.3 图像金字塔2.4 P-Net2.5 R-Ne…

戴尔科技推出全新96核Precision 7875塔式工作站

工作站行业一直是快节奏且充满惊喜的。在过去25年中,戴尔Precision一直处于行业前沿,帮助创作者、工程师、建筑师、研究人员等将想法变为现实,并对整个世界产生影响。工作站所发挥的作用至关重要,被视为化不可能为可能的必要工具。如今,人工智能(AI)和生成式AI(GenAI)的浪潮正在…

西南科技大学C++程序设计实验二(类与对象一)

C++最大的特点就是面向对象,掌握它的几种基本性质还是好理解的,可以看我C++专栏的期末速成,希望对你们学习C++有帮助。 一、实验目的 1.理解简单类的定义、说明与使用 2.理解类中不同属性数据成员的访问特点 3.理解构造函数、析构函数的作用 重点:掌握类的定义与实现,…

MPPT工作流程及算法和硬件的选择

MPPT算法选择 目前,MPPT算法有开路电压比率(离线)、短路电流比率(离线)、观察调节(在线)、极限追踪控制法(在线)。 在光伏控制系统中,因为日照、温度等条件的变化,光伏电池的输出功率也是在不断变化的,为保证使得光伏电池的输出功…

vue3中的customRef创建一个自定义的 ref对象

customRef 创建一个自定义的 ref&#xff0c;并对其依赖项跟踪和更新触发进行显式控制 小案例: 自定义 ref 实现 debounce <template><div style"font-size: 14px;"><input v-model"text" placeholder"搜索关键字"/><…

linux shell下除了某个文件外的其他文件全部删除的命令

Linux反选删除文件 最简单的方法是 # shopt -s extglob &#xff08;打开extglob模式&#xff09; # rm -fr !(file1) 如果是多个要排除的&#xff0c;可以这样&#xff1a; # rm -rf !(file1|file2) Linuxrm删除指定文件外的其他文件方法汇总 一、Linux下删除文…

【Python】导入Excel数据表的几种方式

如何导入csv、xlsx格式的Excel&#xff1b;一张数据表里有多个sheet页&#xff0c;如何获取所有sheet页名字&#xff0c;并导入每张sheet页&#xff1b; 1. 导入CSV格式的Excel表&#xff1a; import pandas as pd import numpy as npdf_datapd.read_csv(数据底表.csv) print…

渗透测试考核--两层内网 cs windows socks5

这里考核为渗透 这里是网络拓扑图 这里记录一下 两台外网 两台内网 首先拿到C段 nmap进行扫描 外网1 nmap -p 80 172.16.17.2/24 主机存活 一般都是web服务入手 所以我们指定80端口 然后去查找开放的 最后获取到2个ip Nmap scan report for 172.16.17.177 Host is u…

如何高效批量生成条形码?

条形码作为商品、库存和信息管理的基础工具&#xff0c;扮演着至关重要的角色。为了满足用户对于高效、专业、多样化的条形码生成需求&#xff0c;我们推出了一款专业高效的在线条形码生成工具。 网址&#xff1a;https://www.1txm.com/ 多样化条形码支持 易条形支持多种常见…

java文件传输简单方法

java文件传输简单方法 假设现在已经打包了一个文件&#xff08;1233444333&#xff09;&#xff0c;要将这个文件传输给另一方&#xff1a; import java.io.*; public class F_PasswordUnPassword { public static void main (String[] args)throws Exception { ByteArrayOutp…

评价体系如何构建?

本文将针对权重计算的一些常见问题进行说明&#xff1a;如组合赋权法的综合权重值如何计算&#xff1f;多层级权重如何计算&#xff1f;用多种方法计算得到的权重如何合并为综合权重用于之后的分析&#xff1f;常见的不同权重计算方法的搭配方式&#xff1f; 一、九种权重计算…

nodejs之express学习(1)

安装 npm i express使用 // 导入 const express require(express) // 创建应用 const app express() // 创建路由 app.get(/home,(req,res)>{res.end("hello express") }) app.listen(3000,()>{console.log("服务已启动~") })路由的介绍 什么是…

5.27每日一题(判断函数在那个区间上有界:充分条件不是必要条件)

若f(x)在(a , b)上连续&#xff0c;且f(a0)&#xff0c;f&#xff08;b-0&#xff09;存在&#xff08;及函数的左右极限存在&#xff09;>f(x)在(a,b)上有界