进程保活之oom_adj级别查询

本文介绍了Android系统中,当内存不足时如何根据oom_adj值判断进程优先级。oom_adj值越小,进程优先级越高,系统更不易杀死。通过`adb shell ps`和`cat /proc/进程id/oom_adj`可以查询进程的oom_adj值。在资源紧张时,adj值为-17的native进程会被系统保留。理解这一机制对实现进程保活至关重要。

  

  当系统的内存不足时, Android系统将根据进程优先级选择杀死一些不太重要的进程。那么进程的优先级是怎样判别的呢?对,就是这个根据进程的oom_adj值。oom_adj的值越小,进程的优先级越高。如果oom_adj的值为 NATIVE_ADJ 即为-17,那么,程序为native级别永驻内存了。

  1.获取当前连接的所有设备

在DOS下使用 adb devices命令  


上面标示有两个设备在线,一个模拟机,一个真机。

注意,这里使用的是devices 不是device 如果使用 adb device 则会打印本地安卓调试桥信息



2.选中要使用的目标 adb -s 设备名 命令

例如 adb -s emulator-5554 shell


出现root@generic_x86:/ # 即获取到模拟机的root权限。

在 Linux 系统中,`oom_adj`、`oom_score` 和 `oom_score_adj` 是与 **OOM Killer(Out-of-Memory Killer)** 相关的进程级参数,用于控制进程在内存不足时被内核终止的优先级。以下是它们的详细解释和关系: --- ### 1. **参数定义与作用** #### (1)`oom_score_adj`(推荐使用) - **路径**:`/proc/[pid]/oom_score_adj` - **范围**:`-1000` 到 `1000` - **作用**: - 调整进程OOM 优先级,**值越低**(如 `-1000`)越**不可能**被杀死,**值越高**(如 `1000`)越**容易被杀死**。 - 替代旧版的 `oom_adj`,提供更精细的控制(支持负值)。 - **示例**: - 设为 `-1000`:进程几乎不会被 OOM Killer 终止(如关键系统进程)。 - 设为 `1000`:进程会优先被杀死(如内存密集型后台任务)。 #### (2)`oom_adj`(旧版,已废弃) - **路径**:`/proc/[pid]/oom_adj` - **范围**:`-16` 到 `15` - **作用**: - 旧版 Linux 用于调整 OOM 优先级,但范围有限且不支持负值(`-17` 表示禁止 OOM Killer,但实际无效)。 - **已废弃**,建议使用 `oom_score_adj`。 - **转换关系**: 内核内部会将 `oom_adj` 转换为 `oom_score_adj`,公式为: ```math oom\_score\_adj = oom\_adj \times \frac{17}{1000} ``` 但直接写入 `oom_adj` 时,内核会按比例映射到 `oom_score_adj` 的范围(如 `-16` → `-1000`,`15` → `1000`)。 #### (3)`oom_score`(只读) - **路径**:`/proc/[pid]/oom_score` - **范围**:`0` 到 `∞` - **作用**: - 表示进程当前的 **OOM 杀伤分数**,由内核根据以下因素计算: - 进程的 `oom_score_adj` 值。 - 进程占用的内存大小(RSS,实际物理内存)。 - 其他内核内部规则(如进程的 UID、是否为内核线程等)。 - **值越高**,进程越容易被杀死。 --- ### 2. **参数关系与计算** #### (1)`oom_adj` 与 `oom_score_adj` 的转换 用户提供的 `oom_adj` 值会通过以下公式转换为 `oom_score_adj`: ```math oom\_score\_adj = oom\_adj \times \frac{17}{1000} ``` 但实际内核处理时,会按比例缩放到 `oom_score_adj` 的完整范围(`-1000` 到 `1000`)。例如: - `oom_adj = -16` → `oom_score_adj = -1000`(禁止杀死) - `oom_adj = 15` → `oom_score_adj = 1000`(最高优先级杀死) #### (2)`oom_score` 的计算 内核根据以下公式计算 `oom_score`: ```math oom\_score = \text{进程内存占用} \times \text{调整因子} + \text{其他修正项} ``` 其中 **调整因子** 由 `oom_score_adj` 决定: - 若 `oom_score_adj > 0`:`oom_score` 会显著增加(容易被杀)。 - 若 `oom_score_adj < 0`:`oom_score` 会减小(受护)。 --- ### 3. **用户示例分析** 假设某进程的参数如下: ```bash oom_adj: -13 oom_score: 0 oom_score_adj: -800 ``` #### (1)验证 `oom_adj` 与 `oom_score_adj` 的关系 根据公式: ```math oom\_score\_adj = oom\_adj \times \frac{17}{1000} = -13 \times \frac{17}{1000} = -0.221 ``` 但实际 `oom_score_adj` 显示为 `-800`,说明: - 用户直接写入了 `oom_score_adj`(而非通过 `oom_adj` 间接设置)。 - 此时 `oom_adj` 的值是内核根据 `oom_score_adj` 反向计算得出的(不精确,仅用于兼容旧接口)。 #### (2)`oom_score` 为 0 的原因 - 进程可能占用内存极少,或 `oom_score_adj` 的负值足够大,使得最终分数被内核修正为 0(表示受强护)。 - 内核可能对关键进程(如 UID=0 的进程)有额外护逻辑。 --- ### 4. **关键注意事项** 1. **优先使用 `oom_score_adj`**: - `oom_adj` 已废弃,且范围有限(`-16` 到 `15`),无法提供精细控制(如 `-800`)。 2. **`oom_score` 是结果,非配置项**: - 用户只能通过调整 `oom_score_adj` 间接影响 `oom_score`。 3. **内核护机制**: - 即使 `oom_score_adj` 设为 `-1000`,某些进程(如内核线程)仍可能被杀死。 4. **Android 的特殊处理**: - Android 的 `lmkd` 会动态调整 `oom_score_adj`,优先级可能与普通 Linux 不同(如更激进的回收策略)。 --- ### 5. **实际应用场景** #### (1)护关键进程 ```bash echo -1000 > /proc/[pid]/oom_score_adj # 禁止被 OOM Killer 杀死 ``` #### (2)强制杀死高内存占用进程 ```bash echo 1000 > /proc/[pid]/oom_score_adj # 标记为最高优先级杀死 ``` #### (3)查看当前 OOM 优先级 ```bash cat /proc/[pid]/oom_score # 查看实际分数 cat /proc/[pid]/oom_score_adj # 查看调整值 ``` --- ### 6. **与 `lowmemorykiller` 的关系** - Android 的 `lowmemorykiller` 直接读取 `oom_score_adj`,而非依赖 `oom_score`。 - 当系统内存不足时,`lowmemorykiller` 会按 `oom_score_adj` 的阈值(如 `adj` 参数)杀死进程,而非依赖内核的 `oom_killer`。 --- ### 示例命令总结 | 操作 | 命令 | |------|------| | 禁止进程被杀死 | `echo -1000 > /proc/[pid]/oom_score_adj` | | 标记为高优先级杀死 | `echo 1000 > /proc/[pid]/oom_score_adj` | | 查看当前分数 | `cat /proc/[pid]/oom_score` | | 查看调整值 | `cat /proc/[pid]/oom_score_adj` | --- ### 关键问题与注意事项 1. **为什么 `oom_score` 可能为 0?** - 进程内存占用极低,或 `oom_score_adj` 的负值完全抵消了内存权重。 2. **`oom_adj` 和 `oom_score_adj` 的优先级?** - 直接写入 `oom_score_adj` 会覆盖 `oom_adj` 的设置,反之则不成立(因 `oom_adj` 已废弃)。 3. **内核如何处理 `oom_score_adj = -1000` 的进程?** - 通常跳过 OOM Killer,但极端情况下(如系统完全卡死)仍可能被杀死。 4. **Android 与普通 Linux 的 OOM 行为差异?** - Android 的 `lowmemorykiller` 主动管理进程,而非完全依赖内核的 `oom_killer`。 5. **`oom_score` 的计算公式是否公开?** - 内核源码中定义(如 `mm/oom_kill.c`),但具体实现可能因版本而异。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值