Linux 内核技术实战课
邵亚方
前蘑菇街技术专家,Linux Kernel 活跃贡献者
23704 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 26 讲
Linux 内核技术实战课
15
15
1.0x
00:00/00:00
登录|注册

08 案例篇 | Shmem:进程没有消耗内存,内存哪去了?

VmallocUsed
KernelStack
Slab
解决方案
tmpfs的影响
tmpfs的特点
内核消耗的内存
tmpfs
其他不体现在进程内存中的内存类型
Shmem的特殊情况
Shmem的含义
内核Bug
Shmem内存泄漏
怀疑态度
配置合适的OOM策略
分析方法
OOM killer的问题
调整oom_score_adj
OOM killer的逻辑
难以观察的内存泄漏
可观察的内存泄漏
课后作业
课堂总结
OOM杀进程的危害
进程内存泄漏
Shmem内存泄漏分析

该思维导图由 AI 生成,仅供参考

你好,我是邵亚方。
在前一节课,我们讲述了进程堆内存的泄漏以及因为内存泄漏而导致的 OOM 的危害。这节课我们继续讲其他类型的内存泄漏,这样你在发现系统内存越来越少时,就能够想到会是什么在消耗内存。
有的内存泄漏会体现在进程内存里面,这种相对好观察些;而有的内存泄漏就很难观察了,因为它们无法通过观察进程消耗的内存来进行判断,从而容易被忽视,比如 Shmem 内存泄漏就属于这种容易被忽视的,这节课我们重点来讲讲它。

进程没有消耗内存,内存哪去了?

我生产环境上就遇到过一个真实的案例。我们的运维人员发现某几台机器 used(已使用的)内存越来越多,但是通过 top 以及其他一些命令,却检查不出来到底是谁在占用内存。随着可用内存变得越来越少,业务进程也被 OOM killer 给杀掉,这给业务带来了比较严重的影响。于是他们向我寻求帮助,看看产生问题的原因是什么。
我在之前的课程中也提到过,在遇到系统内存不足时,我们首先要做的是查看 /proc/meminfo 中哪些内存类型消耗较多,然后再去做针对性分析。但是如果你不清楚 /proc/meminfo 里面每一项的含义,即使知道了哪几项内存出现了异常,也不清楚该如何继续去分析。所以你最好是记住 /proc/meminfo 里每一项的含义。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Shmem内存泄漏是一种难以观察的内存泄漏类型,因为它不会通过观察进程消耗的内存来进行判断。本文介绍了一种特殊的Shmem——tmpfs,它是一种内存文件系统,存在于内存中,不会体现在进程的内存占用上。作者通过一个真实案例讲述了遇到Shmem内存泄漏的问题,以及如何通过查看/proc/meminfo和df命令来定位和分析Shmem内存泄漏的原因。文章还提到了解决方案,如限制tmpfs大小、定期清理临时日志等。此外,还介绍了其他一些类型的内存,如Slab、KernelStack和VmallocUsed,它们也不会体现在进程内存中,需要在排查内存占用时加以注意。 文章还详细介绍了OOM killer的作用和逻辑,以及如何调整进程的oom_score_adj来影响OOM killer的行为。此外,还讲述了在Kubernetes环境下触发的一个内核Bug,并提到了作者为社区贡献的修复该Bug的patch。 在课堂总结中,强调了对不同内存类型特点的了解对于分析内存问题的重要性,以及如何配置合适的OOM策略来防止重要业务被过早杀掉。最后,提出了课后作业,鼓励读者运行程序并观察oom_score和进程被杀的顺序,以加深对文章内容的理解。 总的来说,本文通过介绍Shmem内存泄漏、OOM killer的作用和调整方法,以及内核Bug的案例,为读者提供了对系统内存问题排查和解决的有益参考。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Linux 内核技术实战课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(11)

  • 最新
  • 精选
  • springchan
    老师您好, 有一个疑问:tmpfs是一种基于内存的虚拟文件系统,存储空间是在虚拟内存里,重启机器后会丢失,但是我用mmap 在tmpfs下面映射文件以后,通过使用stat 查看tmpfs下面的文件,为什么会占用block 块呢?block 块不是硬盘的空间么?

    作者回复: tmpfs是存储在内存中,但是它是使用文件方式来管理的,所以也会有block的概念,它的block size跟page大小是一致的,也是4k,但是tmpfs不是块设备。

    2020-09-17
    11
  • 欧阳洲
    老师好,看完这一讲有两个疑问想请教: (1)tmpfs的特点是快,那么与内存有什么不同呢? 假设一个app只有白天可访问,晚上不提供服务。 白天用tmpfs,晚上再来做耗时的部分:写磁盘,清理tmpfs。 那这样的话,为什么白天不直接存储在内存就好,不必写入tmpfs吧? (2)tmpfs与mmap有什么区别和联系吗,除了mmap属于进程,tmpfs不属于进程之外。

    作者回复: 1. tmpfs是内存的一种使用形式,tmpfs里的内容都在内存中。 文件内容在内存中可能会被回收掉,而tmpfs不用担心这个问题;如果你不想被回收,那就需要mlock它。所以tmpfs的优势是使用方便。 2. mmap是接口,tmpfs是存储方式。二者位于不同的层,mmap也可以使用tmpfs,如果进程mmap方式打开tmpfs文件还没有unmap它,那这部分tmpfs内存是属于进程地址空间的。

    2020-09-10
    6
  • KennyQ
    有几个问题: 1. 哪些进程会去使用tmpfs? 2. 如何使用tmpfs,是在启动进程的时候把代码嵌入进去?还是说有接口可以调用? 3. tmpfs是怎么被挂载起来的?重启后是否会自动挂载? 4. tmpfs如果被100个进程调用了,会挂载100次么? 5. 启动tmpfs后是否会修改/etc/mtab? 6. tmpfs使用是否有最佳实践? 7. tmpfs是否可以在线扩缩容?

    作者回复: 1. 很多应用程序会把日志保存在tmpfs里,也有些应用会把它的运行时文件保存在tmpfs里。比如systemd就会把日志记录到tmpfs中。你可以用mount命令来查看你的系统tmpfs挂载路径,然后去这里面查看有哪些文件,你也可以看出来你的系统里有哪些应用会用到tmpfs. 2. 最简单的使用方式是把tmpfs给mount到一个路径上 然后你的应用往里面写文件就可以使用它了。 3. 通过mount命令来挂载,为了重启后也生效,你可以在启动脚本里来挂载。 4. 不会,只需要挂载一次 然后所有进程都可以用了 使用方式上跟普通文件路径没有差异。 5. 会的。 6. tmpfs的目的是针对那些读写io频繁,但数据量不大的场景。既避免了io,又不浪费太多内存。如果你的业务有这种场景,你可以考虑。 7. 可以的 remount可以改变它的大小。

    2020-09-06
    6
  • J.Smile
    要点总结: ①tmpfs ,可以通过 df -h来看是不是 tmpfs 占用的内存较多 ②tmpfs 作为一种特殊的 Shmem,它消耗的内存是不会体现在进程内存中的,这往往会给问题排查带来一些难度。 ③可以通过 /proc/meminfo 找到哪种类型的内存开销比较大,来作为一种辅助手段,比如找到就是tempfs类型的内存,紧接着就可以分析tmpfs的内存占用情况。

    作者回复: 总结的不错 赞!

    2020-10-11
    1
  • qinsi
    看了下那个patch,为啥原始代码里要把负分给截断阿,是有什么特别的考虑吗

    作者回复: 没有特别的考虑,只是因为没有考虑到会存在大量进程设置为负分的这种场景。

    2020-09-09
  • ray
    老师您好, 请问我们该怎么判断一个process会不会使用到tmpfs呢? 谢谢老师的解答^^

    作者回复: 如果进程打开的tmpfs文件还没有close,那么从进程打开的fd里就能看到这些内存文件(比如通过lsof);如果还没有unmap()掉它从tmpfs里申请的内存,那么从进程的地址空间里是可以观察到这些tmpfs内存的。而如果进程已经close掉了它打开的tmpfs文件,那就无法通过进程来分析了,但是通常tmpfs文件里的文件名都会加上进程的一些相关标记,以方便观察是哪个应用创建的。所以我的建议是,你在使用tmpfs文件时,最好这些文件名能够跟你的业务有些关联。

    2020-09-06
  • jssfy
    这个patch很赞!请问老师这个mm oom的bug在centos 7下是否也有?

    作者回复: 对的 这个bug在centos7上也存在 可以backport到centos7上。

    2020-09-05
  • 飞翔
    我这里有一个这样的问题,服务器集群每隔一段时间就有机器进入死机状态,可以ping通,但是ssh连不上, 这时候就得联系现场人员去重启机器,很麻烦。怀疑是内存耗尽的原因,但是重启机器后,从message日子又看不到证据,oom是不是不一定会释放内存? 这种问题应该怎么定位呢?有什么解决方案呢?

    作者回复: 你的内核版本是什么?在老版本内核里,oom如果杀的进程阻塞在内核态的话,比如处于D状态 ,那这个进程的anon内存就没有办法释放;如果是新版本的话,oom会唤醒oom_reaper 然后这个reaper会释放阻塞的进程的内存。所以这类问题的解决方案是,backport oom reaper机制,或者升级内核。定位手段是,你可以使用sysrq -w来看是否这个被杀的进程处于d状态。

    2020-09-05
    3
  • 冬风向左吹
    /PROC/MEMINFO之谜:http://linuxperf.com/?p=142
    2020-09-05
    9
  • Linuxer
    赞!意犹未尽,爽!
    2020-09-05
    2
收起评论
显示
设置
留言
11
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部