工作学习笔记-oom killer详解

本文详细介绍了Linux操作系统中的OOM Killer机制,当系统内存不足时如何选择并终止内存消耗过多的进程。内容涵盖OOM Killer的工作原理、选择进程的依据、实战案例以及常见GFP内存分配掩码的解析。通过对oom_adj、oom_score_adj和oom_score的分析,帮助理解哪些进程可能被杀死。


前言

本篇文章一起探讨下oom-killer相关问题


一、oom-killer是什么?

在 Linux 操作系统中,OOM Killer(Out-Of-Memory Killer)是一个内核机制,用于在系统内存不足时选择并终止消耗过多内存的进程,以便释放内存并保持系统的正常运行。
当系统内存不足以满足进程的需求时,Linux 内核会试图通过交换部分内存页到交换空间(swap space)或者使用页面回收技术(比如删除长时间不活动的页面)来释放内存。然而,如果这些方法仍然无法满足系统的内存需求,内核就会触发 OOM Killer。

二、oom杀死进程的原理

OOM Killer 的工作原理是扫描系统中的进程,评估它们各自的内存使用情况,并选择一个最适合终止的进程来释放内存。通常情况下,OOM Killer 会选择那些消耗大量内存但对系统整体影响较小的进程作为终止目标。然而,并非所有进程都能被终止,因为有些进程可能是关键的系统进程或者用户态进程,终止它们可能会导致系统崩溃或数据丢失。
在系统触发 OOM Killer 后,内核会记录相关信息,如触发 OOM 条件的进程、OOM Killer 杀死的进程等,以便后续分析和故障排除。

三、什么进程会被oom杀死

每个进程的/proc/PID/oom_adj、oom_score_adj和oom_score记录着进程分数
oom_adj、oom_score_adj和oom_score:用来控制进程打分(分数越高,就先杀谁)

四、实战

在这里插入图片描述
如上如flb-pipline进程就被干掉了
后面的gfp-mask代表表示进程请求内存时使用的 GFP(Get Free Pages)掩码。GFP 掩码用于指定内核在内存分配时应该遵循的一系列规则和属性。不同的 GFP 掩码代表了不同的内存分配类型和属性。以下是常见的 GFP 掩码类型及其含义:

GFP_KERNEL:该掩码用于普通的内核内存分配请求。当进程需要从内核中分配内存时,通常会使用该掩码。这种分配可以等待,因此内核可能会尝试通过回收内存或交换内存页来满足请求。

GFP_ATOMIC:该掩码用于请求不可阻塞的、原子级别的内存分配。这种分配是非阻塞的,因此如果没有可用内存,内核将立即返回失败,而不是等待。通常用于处理中断上下文或者在内核关键路径上。

GFP_DMA:该掩码用于请求可用于 DMA(直接内存访问)的内存。DMA 内存通常要求物理地址连续,因此需要使用特定的内存分配方法。

GFP_HIGHUSER:该掩码用于请求高优先级用户内存。这种分配通常用于用户空间应用程序,例如驱动程序或用户态工具,这些应用程序需要较低的延迟和可预测的内存分配性能。

GFP_NOIO:该掩码用于请求不会导致 IO 操作的内存分配。这种分配通常用于处理 IO 系统调用或者在不能阻塞 IO 的上下文中。

GFP_NOFS:该掩码用于请求不会引发文件系统操作的内存分配。这种分配通常用于在文件系统代码中防止递归调用导致的死锁。

GFP_NOFAIL:该掩码用于请求不会失败的内存分配。如果无法分配所需内存,则内核会尝试使用 OOM Killer 终止其他进程以释放内存。

GFP_THISNODE:该掩码用于请求在当前 NUMA 节点上分配内存。

这些是常见的 GFP 掩码类型,每种类型都代表了不同的内存分配需求和属性。在触发 OOM Killer 后,系统日志中的 gfp_mask 将指示触发 OOM 条件的进程使用的 GFP 掩码,以及它们的内存分配属性。


order= 代表内核在尝试进行内存分配时所请求的页面数量的对数。这个参数通常用于跟踪触发 OOM 的具体内存分配请求的大小。

在 Linux 内核中,内存分配通常以页为单位进行,每个页的大小取决于系统的配置,通常为 4KB 或 8KB。当内核尝试进行内存分配时,它通常会请求一定数量的连续页面来满足请求。order= 参数指定了请求页面数量的对数,即请求页面的数量等于 2 的 order 次方。

例如,如果系统日志中记录了 order=2,则表示内核尝试进行的内存分配请求的页面数量为 2 的平方,即 4 个页面。这意味着内核试图一次性分配连续的 4 个页面来满足特定的内存分配需求


在这里插入图片描述
oom后有calltrace和meminfo信息,用来查看具体哪个部分用了较多的内存
在这里插入图片描述
从上图我们可以看出这些信息:
1、这也不是系统级别的oom,而是cgroup级别的
2、这个k8s的cgroup组限制了内存使用为204800,这个组内进程的rss 用了203168,cache 1148…(后面还有各种类型内存占用我就不打了)
3、最终结果就是他们进程内存占用超过了他们设置的内存上限204800
综上所述,这个就需要从应用侧来看,进程占用这么多合不合理,合理的话就要调大cgroup memory.limit限制,从系统角度来说,这个cgroup组都不是系统管理的,应该是又k8s应用方设置的,基本都是k8s上层做了限制,然后对应的管理软件在自己建立了cgroup组管理。
在这里插入图片描述
在这里插入图片描述

总结

oom相关问题持续更新,以后有相关oom问题会继续记录在这里

<think> 首先,用户的问题是关于“OOM killer enabled”,意思是想了解OOM Killer启用的原因、影响和解决办法。用户提供了三个引用,我需要参考这些内容来构建回答。 回顾引用内容: - 引用[1]:解释了OOM Killer是内核在内存严重不足时触发的机制,终止进程释放内存。提到了OOM分数、内核参数、Cgroup限制等。 - 引用[2]:讨论了OOM Killer机制,当一个进程挂掉时,可能由于内存不足触发OOM Killer- 引用[3]:提到Android系统中有一个OOM进程,作为OOM Killer,并涉及oom_adj值。 用户的查询是具体关于“OOM killer enabled”,这似乎指的是OOM Killer被启用或触发的场景。OOM Killer通常是Linux内核的一部分,总是在运行,但会在特定条件下被触发。 关键点是: - 原因:当系统内存严重不足时,内核触发OOM Killer- 影响:它会终止进程(通常是占用内存最多的进程),可能导致服务中断、数据丢失等。 - 解决办法:包括调整内核参数、使用Cgroup限制内存、优化应用程序以减少内存使用等。 我的回答需要: - 使用中文回答。 - 结构清晰,分为原因、影响、解决办法等部分。 - 在行内数学表达式用$...$,独立公式用$$...$$(但这里可能不需要数学公式,除非涉及计算)。 - 添加引用标识在段落末尾,如[^1]。 - 生成相关问题。 回答结构: 1. 引入OOM Killer。 2. 解释启用的原因(触发条件)。 3. 描述影响。 4. 提供解决办法。 5. 结尾并生成相关问题。 确保引用正确: - 引用[1]和[2]来自用户提供的引用,我需要基于这些内容,自然地添加引用标识。 生成相关问题: - 在回答末尾,添加"§§相关问题§§",然后列出几个相关的问题,如如何监控OOM事件、如何配置OOM Killer等。 最终回答框架: - 第一部分:介绍OOM Killer和启用的原因。 - 第二部分:影响。 - 第三部分:解决办法。 - 第四部分:相关问题。 </think> ### OOM Killer 启用的原因、影响及解决办法 OOM Killer(Out-Of-Memory Killer)是 Linux 内核中的一个紧急机制,当系统内存严重不足时自动触发,其目的是通过终止选定的进程来释放内存,从而防止系统崩溃或卡死。OOM Killer 的启用并非一个独立的“开关”,而是内核在特定条件下自动激活的过程。以下我将从原因、影响及解决办法三个方面详细解释,基于您提供的引用内容。 #### 一、OOM Killer 启用的原因 OOM Killer 被触发的主要原因在于系统内存资源耗尽。具体包括: - **内存严重不足**:当所有可用内存(包括物理内存和交换空间)都被耗尽时,内核无法为新进程分配内存或为现有进程扩展内存需求,此时 OOM Killer 会被激活以强制释放资源。引用中提到,"系统内存不足导致触发了 Linux 操作系统 OOM killer 机制"[^2]。 - **内核参数配置**:某些内核参数(如 `vm.overcommit_memory`)可能导致内存过度承诺(overcommit),增加 OOM 风险。默认情况下,内核允许进程申请超过实际可用内存的空间,但当实际使用时内存不足,便会触发 OOM Killer[^1]。 - **应用程序行为**:应用程序设计不当(如内存泄漏或突发性高内存需求)会导致内存使用激增,超出系统承受能力。例如,一个占用大量内存的进程可能被优先终止[^1]。 - **Android 系统差异**:在 Android 中,OOM Killer 进程专门用于管理应用程序,其启用取决于 `oom_adj` 值(范围 -16 到 15),值越低表示进程越重要,不易被终止。系统根据应用优先级动态调整,当内存不足时触发[^3]。 总之,OOM Killer 启用的根本原因是系统内存资源枯竭,无法通过正常回收机制缓解,内核被迫介入以维持系统稳定[^1][^2]。 #### 二、OOM Killer 启用的影响 OOM Killer 的触发虽然保护了系统整体稳定性,但会带来一系列负面影响: - **进程意外终止**:OOM Killer 会基于每个进程的 OOM 分数(根据内存占用、优先级等计算)选择并终止目标进程。这可能导致关键服务(如数据库或 Web 服务器)突然中断,造成服务不可用或数据丢失。引用描述,"程序运行了一段时间,有个进程挂掉了,正常情况下进程不会主动挂掉",这反映了进程被强制终止的后果[^2]。 - **系统性能波动**:内存释放过程中,系统可能经历短暂的性能下降或卡顿,尤其是在高负载环境下。 - **业务中断风险**:在生产环境中,频繁触发 OOM Killer 可能影响服务质量(QoS),降低用户体验或造成经济损失。例如,在 Android 系统中,低优先级的应用更容易被终止,可能导致后台任务失败[^3]。 - **调试困难**:进程被终止后,可能缺乏清晰的日志记录(尽管内核日志会记录 OOM 事件),增加了问题诊断的复杂度[^1]。 影响程度取决于被终止进程的重要性:如果终止的是非关键进程,系统可能快速恢复;但如果涉及核心服务,则可能导致级联故障[^2][^3]。 #### 三、OOM Killer 启用的解决办法 针对 OOM Killer 的触发,解决办法主要从预防和缓解两方面入手,目标是减少内存不足事件的发生频率或控制其破坏性: 1. **优化应用程序**: - 修复内存泄漏:使用工具(如 Valgrind 或 Java Heap Dump)检测并修复代码中的内存泄漏问题。 - 限制内存使用:在应用程序中添加内存使用上限配置,例如在 Java 应用中设置 `-Xmx` 参数来控制堆大小[^2]。 - 合理设计资源分配:避免突发性高内存需求,采用缓存机制或分批处理数据。 2. **配置内核参数**: - 调整 overcommit 设置:修改 `/etc/sysctl.conf` 文件中的参数,例如设置 `vm.overcommit_memory = 2`(禁止过度承诺内存),以减少 OOM 风险。命令示例: ```bash sysctl vm.overcommit_memory=2 ``` - 设置 OOM 分数优先级:通过 `oom_score_adj` 文件(位于 `/proc/<pid>/`)调整进程的 OOM 分数,降低关键进程被终止的概率。例如,设置值為 -1000(最小值)使进程更难被终止[^1][^3]。 3. **使用资源限制工具**: - **Cgroups(控制组)**:在 Linux 系统中,利用 Cgroups 对进程组内存使用进行硬性限制。例如,通过 `cgroup` 目录配置内存上限(如 `memory.max`),确保单个进程或容器不会耗尽系统内存。这在生产环境中是推荐的做法,能显著降低 OOM 事件频率[^1]。 - **容器化部署**:在 Docker 或 Kubernetes 中,指定容器的内存限制(如 `docker run -m 512m`),超出时容器自动重启而非触发全局 OOM Killer。 4. **监控与预警**: - 实时监控内存使用:使用工具如 `top`, `free` 或 Prometheus 监控内存占用率,设置阈值告警(如空闲内存低于 10% 时触发)。 - 分析 OOM 日志:检查内核日志(`dmesg` 或 `/var/log/kern.log`)获取 OOM 事件的详细信息,识别高风险进程[^1][^2]。 5. **Android 特定策略**(如适用): - 调整 `oom_adj` 值:在 Android 开发中,通过 AmS(Activity Manager Service)设置应用程序的优先级,避免重要应用被终止[^3]。工具如 `procrank` 可帮助分析内存占用。 总之,解决办法的核心是“事前预防为主”,通过资源限制和优化降低 OOM 概率;同时,“事后缓解为辅”,确保关键进程不被误杀。如果 OOM Killer 频繁触发,建议优先排查应用程序问题或升级系统内存资源[^1][^2][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值