文档章节

内存管理之12:守护进程kswapd

我叫半桶水
 我叫半桶水
发布于 07/15 22:58
字数 1977
阅读 45
收藏 0

date: 2014-10-10 19:09

1 kswapd的创建

为了避免总在CPU忙碌时也就是缺页异常发生时,临时再来搜寻空换出的页面进行换出,内核将定期检查并预先将若干页面换出以腾出空间,维持系统空闲内存的的保有量,以减轻系统在缺页异常发生时的负担。为此内核设置了一个专司页面换出的守护神kswapd进程。

kswapd进程是个内核进程,这意味着,一方面kswapd没有对应用户空间(只有系统空间),但是有对应task_struct结构(因此调度器可能对它进行调度);一方面进程的可执行代码与内核链接在一起(编译到内核镜像中),因此他可以自由访问内核中的全局函数。

kswapd进程创建的代码如下:

    <mm/vmscan.c>

    static int __init kswapd_init(void)
    {
	    printk("Starting kswapd v1.8\n");
	    swap_setup();
	    kernel_thread(kswapd, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
	    kernel_thread(kreclaimd, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
	    return 0;
    }

kswapd_init在系统初始化期间被调用,它通过调用kernel_thread创建了两个内核进程kswapd和kreclaimd。kernel_thread的第一参数为“进程入口函数”,kswapd进程对应的进程函数为kswapd(其实进程的名字是在kswapd函数中设置的),kswapd函数的实现在同一文件中。下文主要分析kswapd函数的流程。

2函数调用关系

kswapd流程

2.1 kswapd

在进行一些简答的初始化后,kswapd进入一个死循环。死循环中的操作可以分为两部分:第一部分是当内存短缺时调用do_try_to_free_pages,目的在于预先找出若干页面,将这些页面的映射断开,并且使之从活跃状态变为不活跃状态,为页面换出做准备。第二部分是例行公事,每个循环都会做的,那就是把不活跃的脏页面写入交换设备,使它们成为不活跃干净页面继续缓冲,或更进一步,回收一些这样的页面使之成为空闲页面。

处理完这两部分工作之后,kswapd已经设法回收了一些页面了,这时可以唤醒哪些因内存不足而转入睡眠的进程(参考内存页面分配流程)。如果本次尝试已经使得系统的有了一定的空闲内存“保有量”,为了不占用CPU时间,kswapd像一个谦谦君子,主动转入睡眠,睡眠时间是1秒,但在睡眠期间运行被提前唤醒。如果内存仍然不足,那就只能忍痛杀死一个进程(oom_kill),牺牲小我成就大我,以此来回收一些内存。

2.2 do_try_to_free_pages

将活跃页面的映射断开,使之转入不活跃状态甚至最终被交换出去,这都是不得已而为之,是内核的一种痛。因此do_try_to_free_pages按照痛的等级从浅到深的顺序来选择页面。先调用page_launder来将不活跃脏页面洗净,使他们变成立即可分配的页面。如果可分配的页面数量仍然短缺,再从三个方面着手:

  • 其一、在打开文件的过程中,要分配代表着目录项dentry的数据结构以及代表着索引节点inode的数据结构,这些数据结构在文件关闭是并没有立即释放,而是放到LRU队列中养起来,以备后面打开同一个文件时再用到。这样经过一段时间以后,系统中积累起大量的这种结构,占据着可观的物理页面,是时候将它们适度回收了,这就是shrink_dcache_memory和shrink_icache_memory函数的作用。
  • 其二、内核中的slab分配器担负着为小对象分配内存的工作,slab一方面从内核“批发”成块的内存页面,再“零售”给内核中的小对象。会哭的孩子有奶吃,slab也倾向于向内核多要内存以作为自己的缓冲,却没有“及时归还”的美德,是时候回收一下了,kmem_cache_reap(“reap”的意思是收割)函数就是用于此目的。
  • 其三、没办法,只能将“场上”的球员换到“替补席”上了。选择若干活跃的页面,使之转入不活跃状态甚至交换出去,这些操作由函数refill_inactive领衔。

2.3 refill_inactive

refill_inactive主要的操作有两层循环,外层循环以扫描力度priority(初始值为6)为终止条件。内层有两个循环,其一是循环调用refill_inactive_scan,扫描全局的活跃页面队列active_list,试图从中找到可以转入不活跃状态的页面,挑选的准则是页面“寿命”(该寿命由kswapd的赐予并由kswapd“倒数”)以及页面使用计数双重标准。当然并不是扫描队列中的每一个页面,扫描力度由priority决定,当priority为0时才扫描每个页面;其二是循环调用swap_out,选择一个进程(选择的准则“劫富济贫”,即找驻内存页面rss最多的进程),然后后扫描其页面映射表,找出其中可以转入不活跃状态的页面。读者也许会问,既然这个页面是有映射的(否则不会出现在进程的页面映射表中),那怎么会不在活跃页面队列active_list中呢?在讲页面换入时我们会看到,当因页面页面而恢复一个不活跃页面的映射时,该页面并不是立即就转到活跃页面队列,而把这项工作留给page_launder,让其在系统比较空闲时再来处理,所以这样的页面有可能不在活跃页面队列中。

refill_inactive_scan和swap_out每次尝试“换出”一个页面,如果空闲内存以及非活跃内存不再短缺,则可提前退出外层循环,如果refill_inactive_scan和swap_out“换出”页面困难,那么外层循环将是一个巨大的循环,将消耗大量的CPU时间。我们在《进程与进程调度》一章将看到在系统调用或者是中断服务程序返回用户空间之前,内核会检查task_struct结构中的need_resched字段,如果该字段置1,则要求调度。但kswapd是个内核进程,永远不会返回用户空间,这样就可能绕过这个检查而占着CPU不放,所以只能靠它“自律”了。在refill_inactive的每次外层循环之前,主动检查current->need_resched并请求一次调度。

前面说过,将页面换出到磁盘页面上时,pte_t已经变身为swp_entry_t,那么swp_entry_t的值从何而来,每次换出都需要重新指定吗?显然,如果该内存页面之前曾换出过,而且从那之后该内存页面的内容没有被改写,意味着页面是干净的,那么只需找到之前的“磁盘页面”,重新建立联系就可以了,并不需要真正的写出到磁盘。而且即使改写了,建立这种一对一的联系也便于我们管理。为了此目的,page结构中有一个index成员(其实就是swp_entry_t),指向该内存页面在磁盘上的“归宿”,需要换出时,根据index找到归宿,必要时,将页面的内容“转移”到对应的磁盘页面上就可以了。

© 著作权归作者所有

共有 人打赏支持
我叫半桶水
粉丝 0
博文 26
码字总数 71642
作品 0
西安
私信 提问
Linux 下10个不得不知道的”系统进程”

在日常的运维工作中,当我们习惯性的执行ps命令后会看到很多“奇奇怪怪”的进程,而这些进程大部门都是系统的内核进程。很多同学对之了解的甚少,因此今天就为大家整理一篇入门级的系统进程介...

Forande
2017/11/10
0
0
kswapd0进程占用大量cpu资源导致挂机

利用top查看, mysql 进程占内存很多, 90%以上, kswapd0 占cpu很多, 250%以上, 相应的mysqld, apache等占内存也很多. 因为是测试机, 开始以为是请求很多, 导致死机. 重启之后, 又很快的死掉了...

linuxqwer
2016/08/04
0
0
kswapd和pdflush

首 先,它们存在的目的不同,kswap的作用是管理内存,pdflush的作用是同步内存和磁盘,当然因为数据写入磁盘前可能会换存在内存,这些缓存真正写 入磁盘由三个原因趋势:1.用户要求缓存马上写...

晨曦之光
2012/04/10
437
0
MySQL · 专家投稿 · MySQL数据库SYS CPU高的可能性分析

问题背景 我们在管理繁忙的 MySQL 数据库时,可能都有碰到 SYS CPU 高的经历:系统突然 SYS CPU 高起来,甚至比 USER CPU 高很多,这时系统 QPS、TPS 急剧下降。 SYS CPU高是什么造成的呢?主...

阿里云RDS-数据库内核组
2015/05/03
0
0
linux系统性能测试之虚拟内存管理篇

虚拟内存管理是 Linux 内核里面最复杂的部分,要弄懂这部分内容可能需要一整本书的讲解。VPSee 在这里只介绍和性能监测有关的两个内核进程:kswapd 和pdflush。 1、kswapd daemon 用来检查 ...

mtoou
2011/04/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Kylin2.5.0环境搭建及操作记录

Apache Kylin是一个开源的分布式分析引擎,提供Hadoop/Spark之上的SQL查询接口及多维分析(OLAP)能力以支持超大规模数据,最初由eBay Inc. 开发并贡献至开源社区。它能在亚秒内查询巨大的H...

PeakFang-BOK
9分钟前
0
0
SpringBoot整合es

文档对像 @Document(indexName = "bigdata",type = "tag")public class User { @Idprivate String openid; private List<String> tags;public String getOpenid() ......

魔法王者安琪拉
13分钟前
0
0
windows下让 jar 在后台运行的办法

windows下 运行 java jar 不出现 命令行 窗口 新建一个披处理 run.bat,内容如下 @echo off start javaw -jar xx.jar exit 双击运行即可。...

glen_xu
22分钟前
4
0
jdk1.8 lambda stream 指定的对象属性进行去重

原因:因为Stream提供的distinct()方法只能去除重复的对象,无法根据指定的对象属性进行去重,可以应付简单场景。 解决方案: //去重,共同信息保存到bizPledgeSupplierVOs里bizPledgeSupp...

INSISTQIAO
25分钟前
0
0
vue nextTick深入理解---vue性能优化、DOM更新时机、事件循环机制

定义[nextTick、事件循环] nextTick的由来: 由于vue的数据驱动视图更新是异步的,即修改数据的当下,视图不会立即更新,而是等同一事件循环中的所有数据变化完成之后再统一进行视图更新。...

JamesView
33分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部