博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux的页面回收与反向映射机制
阅读量:3623 次
发布时间:2019-05-21

本文共 1946 字,大约阅读时间需要 6 分钟。

页面回收的实现

Linux 操作系统进行页面回收需要考虑的方面很多,下图列出了 Linux 操作系统进行页面回收的关键代码流程图,该图给出了实现页面回收的关键代码函数名,并说明它们之间是如何彼此链接的。

图 2. 页面回收关键代码流程图

上文提到 Linux 中页面回收主要是通过两种方式触发的,一种是由“内存严重不足”事件触发的;一种是由后台进程 kswapd 触发的,该进程周期性地运行,一旦检测到内存不足,就会触发页面回收操作。对于第一种情况,系统会调用函数 try_to_free_pages() 去检查当前内存区域中的页面,回收那些最不常用的页面。对于第二种情况,函数 balance_pgdat() 是入口函数。

当 NUMA 上的某个节点的低内存区域调用函数 try_to_free_pages() 的时候,该函数会反复调用 shrink_zones() 以及 shrink_slab() 释放一定数目的页面,默认值是 32 个页面。如果在特定的循环次数内没有能够成功释放 32 个页面,那么页面回收会调用 OOM killer 选择并杀死一个进程,然后释放它占用的所有页面。函数 shrink_zones() 会对内存区域列表中的所有区域分别调用 shrink_zone() 函数,后者是从内存回收最近最少使用页面的入口函数。

对于定期页面检查并进行回收的入口函数 balance_pgdat() 来说,它主要调用的函数是 shrink_zone() 和 shrink_slab()。从上图中我们也可以看出,进行页面回收的两条代码路径最终汇合到函数 shrink_zone() 和函数 shrink_slab() 上。

函数 shrink_zone()

其中,shrink_zone() 函数是 Linux 操作系统实现页面回收的最核心的函数之一,它实现了对一个内存区域的页面进行回收的功能,该函数主要做了两件事情:

●将某些页面从 active 链表移到 inactive 链表,这是由函数 shrink_active_list() 实现的。

●从 inactive 链表中选定一定数目的页面,将其放到一个临时链表中,这由函数 shrink_inactive_list() 完成。该函数最终会调用 shrink_page_list() 去回收这些页面。

函数 shrink_page_list() 返回的是回收成功的页面数目。概括来说,对于可进行回收的页面,该函数主要做了这样几件事情,其代码流程图如下所示:

图 3. 函数 shrink_page_list() 实现的关键功能

●对于匿名页面来说,在回收此类页面时,需要将其数据写入到交换区。如果尚未为该页面分配交换区槽位,则先分配一个槽位,并将该页面添加到交换缓存。同时,将相关的 page 实例加入到交换区,这样,对该页面的处理就可以跟其他已经建立映射的页面一样;

●如果该页面已经被映射到一个或者多个进程的页表项中,那么必须找到所有引用该页面的进程,并更新页表中与这些进程相关的所有页表项。在这里,Linux 2.6 操作系统会利用反向映射机制去检查哪些页表项引用了该页面,关于反向映射的内容在后边会有介绍;

●如果该页面中的数据是脏的,那么数据必须要被回写;

●释放页缓存中的干净页面。

函数 shrink_slab()

函数 shrink_slab() 是用来回收磁盘缓存所占用的页面的。Linux 操作系统并不清楚这类页面是如何使用的,所以如果希望操作系统回收磁盘缓存所占用的页面,那么必须要向操作系统内核注册 shrinker 函数,shrinker 函数会在内存较少的时候主动释放一些该磁盘缓存占用的空间。函数 shrink_slab() 会遍历 shrinker 链表,从而对所有注册了 shrinker 函数的磁盘缓存进行处理。

从实现上来看,shrinker 函数和 slab 分配器并没有固定的联系,只是当前主要是 slab 缓存使用 shrinker 函数最多。

注册 shrinker 是通过函数 set_shrinker() 实现的,解除 shrinker 注册是通过函数 remove_shrinker() 实现的。当前,Linux 操作系统中主要的 shrinker 函数有如下几种:

●shrink_dcache_memory():该 shrinker 函数负责 dentry 缓存。

●shrink_icache_memory():该 shrinker 函数负责 inode 缓存。

●mb_cache_shrink_fn():该 shrinker 函数负责用于文件系统元数据的缓存。

转载地址:http://eakun.baihongyu.com/

你可能感兴趣的文章
SpringCloud-基础设施即服务day5-DockerCompose
查看>>
SpringCloud-平台即服务day6-GitLab
查看>>
SpringCloud-平台即服务day7-Nexus和Registry
查看>>
Spring Security oAuth2
查看>>
2021网易游戏雷火2021春招游戏功能测试工程师 笔试记录----春招补录
查看>>
中国建设银行 AI视频面经 ---浙江省分行 开发运维方向
查看>>
完全理解Docker安装软件,只需三步!
查看>>
整体学习Spring的Bean生命周期(上帝视角)
查看>>
Redis分布式锁逐步完善过程,最后推荐Redisson框架
查看>>
区块链11-区块链去中心化应用开发4-DAPP实战-应用介绍及前置知识
查看>>
大数据Hadoop分布式文件系统HDFS
查看>>
大数据Hadoop 技术内幕:深入解析 HDFS架构设计与实现原理
查看>>
Hadoop 1.x与Hadoop 2.x
查看>>
大数据Hadoop分布式文件系统HDFS的两类节点NameNode和DataNode
查看>>
大数据Hadoop生态圈技术之浅析PageRank计算原理
查看>>
不知道能不能称得上史上最全大数据 高效学习 成就未来
查看>>
select、poll和epoll的区别
查看>>
java网络编程面试题(一)
查看>>
ZooKeeper 典型应用场景一览
查看>>
深入剖析Tomcat性能优化与集群session共享
查看>>