Android oom_adj 更新原理(一)

源码基于:Android R

0. 前言

通过之前的两篇博文《lmkd 机制详解》《oom_adj 内存水位算法剖析》中,根据计算出来的 min_score_adj 选择大于该值的 oom_adj 的进程进行 kill 处理。 oom_adj 随着应用状态的不同其值也是伴随着变化的。

本文将通过源码剖析 oom_adj 更新的原理。

1. adj 概念

Android 系统的设计理念希望应用进程尽可能的长时间的存活,以此来提升用户体验。在Android 中,应用首次打开会比较慢,这个过程包含进程的创建、application 初始化、应用其他逻辑等,所以,在应用退出时并非直接exit 进程或被 kill,而是会存活一段时间,这样就保证在下次启动时跟快启动。

当然,物极必反。在大量应用启动后就会造成内存大量使用,手机性能会随着下降。如果放任所有进程存活,系统内存就会枯竭。因此需要合理的回收机制,An

<think>首先,用户的问题是:“我想调整Android中AMS的oom_adj值 请问Android AMS update oom_adj configuration”。这涉及到Android的Activity Manager Service (AMS)如何更新oom_adj值。 从系统级指令中,我需要: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,如[^1]。 用户可见层要求: - 回答结构清晰,帮助用户逐步解决问题。 - 保证回答真实可靠。 参考提供的引用: - [^1]: AMS 更新进程优先级:1) AMS.applyOomAdjLocked() 设置进程的adj;2) AMS.updateConfiguration() 更新各个级别的oom_adj信息;3) AMS.cleanUpApplicationRecordLocked() 或 handleAppDiedLocked() 移除进程。 - [^2]: 当AMS第次接到configuration change时,更新OOM level,lowmemorykiller的lowmem_autodetect_oom_adj_values()被调用。 - [^3]: AMS.updateConfiguration() 调用 updateOomLevels(),向/sys/module/lowmemorykiller/parameters/ 写入minfree和adj信息。 - [^4]: 描述oom_adjoom_score_adj的转换公式,以及lowmemorykiller如何工作。 - [^5]: 关于Activity启动流程的引用,但可能不直接相关。 用户的问题是关于调整oom_adj值并更新配置。关键是如何通过AMS更新oom_adj配置。 核心步骤: 1. **理解oom_adj**:oom_adjAndroid中用于内存管理的值,表示进程的优先级(越低优先级越高,越不容易被杀死)。 2. **AMS如何更新oom_adj**: - 根据引用[^1],AMS.updateConfiguration() 方法用于更新oom_adj配置。 - 引用[^3] 确认了AMS.updateConfiguration() 调用 updateOomLevels(),写入到/sys/module/lowmemorykiller/parameters/minfree 和 adj。 - 引用[^4] 解释了oom_adjoom_score_adj的转换。 具体过程: - AMS.updateConfiguration() 被调用时,它会更新OOM级别。 - 这涉及到写入lowmemorykiller的参数:minfree(内存阈值)和adj(对应的oom_adj值)。 - 例如,minfree文件包含内存阈值列表,adj文件包含对应的oom_adj值。 调整oom_adj值: - 用户可能想修改默认的oom_adj值或添加自定义值。 - 在Android中,这通常需要修改系统代码或使用特定API。 - 但用户是开发者?可能需要指导如何通过代码调整。 回答结构: 1. **解释oom_adj和AMS的角色**:简要介绍oom_adj和AMS如何管理它。 2. **更新oom_adj配置的机制**:基于引用,描述AMS.updateConfiguration() 的作用。 3. **如何调整值**:提供方法,如修改系统文件或通过代码调用API。 4. **注意事项**:提到权限和风险,因为修改系统文件可能需要root权限。 5. **生成相关问题**:在结尾添加相关问题。 使用中文回答。 在回答中引用段落末尾添加引用标识。例如,解释时提到引用[^1]。 数学表达式:如果有公式,使用LaTeX。例如,引用[^4]中有公式: - lowmem_oom_adj_to_oom_score_adj 函数:如果oom_adj == OOM_ADJUST_MAX,则oom_score_adj = OOM_SCORE_ADJ_MAX;否则,oom_score_adj = (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE。 - OOM_ADJUST_MAX = 15, OOM_SCORE_ADJ_MAX = 1000, OOM_DISABLE = -17. - 所以,公式:如果 $oom\_adj = 15$,则 $oom\_score\_adj = 1000$;否则,$oom\_score\_adj = \frac{oom\_adj \times 1000}{17}$。 在回答中,如果需要,使用行内格式。 生成相关问题:基于主题,如如何手动设置oom_adj,AMS的其他方法等。 完整回答大纲: 1. 介绍:什么是oom_adj和为什么需要调整。 2. AMS更新oom_adj的机制:重点在AMS.updateConfiguration()。 3. 步骤调整:如何通过代码或文件修改。 4. 注意事项。 5. 相关问题。</think>### 调整Android AMS的oom_adj值配置 在Android系统中,`oom_adj`(Out-Of-Memory Adjustment)值用于表示进程的内存优先级(值越低,优先级越高,越不容易被系统杀死)。Activity Manager Service (AMS) 负责动态管理这些值,以优化内存使用。以下是调整和更新`oom_adj`配置的详细步骤和机制,基于Android框架的实现(以Android 10为例)。 #### 1. **理解oom_adj更新机制** AMS 通过以下核心方法更新`oom_adj`配置: - **AMS.updateConfiguration()**:这是关键入口,当系统配置变更(如屏幕旋转、语言切换)或手动触发时,该方法会调用`updateOomLevels()`,更新所有进程的OOM级别。它向Linux内核的lowmemorykiller驱动写入参数,包括: - `/sys/module/lowmemorykiller/parameters/minfree`:内存阈值列表(单位:page)。 - `/sys/module/lowmemorykiller/parameters/adj`:对应的`oom_adj`值列表。 例如,默认配置可能为 `minfree = "18432,23040,27648,32256,55296,80640"` 和 `adj = "0,100,200,300,900,906"`,表示当可用内存低于18432页时,杀死`oom_adj≥0`的进程[^3]。 - **AMS.applyOomAdjLocked()**:针对单个进程设置`oom_adj`值,通常在进程状态变化(如启动或切到后台)时调用。它会直接修改`/proc/<pid>/oom_score_adj`文件(内核使用的实际值)[^1]。 - **移除进程**:当进程结束时,`AMS.cleanUpApplicationRecordLocked()` 或 `handleAppDiedLocked()` 将其从lmkd(Low Memory Killer Daemon)策略中移除[^1]。 `oom_adj` 到 `oom_score_adj` 的转换使用公式: $$ \text{oom\_score\_adj} = \begin{cases} 1000 & \text{if } \text{oom\_adj} = 15 \\ \frac{\text{oom\_adj} \times 1000}{17} & \text{otherwise} \end{cases} $$ 其中,$OOM\_ADJUST\_MAX = 15$,$OOM\_SCORE\_ADJ\_MAX = 1000$,$OOM\_DISABLE = -17$[^4]。 #### 2. **调整oom_adj值的步骤** 若要手动调整`oom_adj`值,需通过系统级操作(**需要root权限**): ##### 方法:修改lowmemorykiller参数(直接写入sysfs) - **步骤**: 1. 获取root权限:`adb root`。 2. 挂载系统分区为可写:`adb remount`。 3. 更新`adj`文件: ```bash adb shell "echo '0,100,200,250,500,900' > /sys/module/lowmemorykiller/parameters/adj" ``` 这里将第三个阈值对应的`oom_adj`从默认300改为250,使该级别进程更容易被杀死。 4. 可选:更新`minfree`以调整内存阈值: ```bash adb shell "echo '12288,18432,24576,30720,55296,80640' > /sys/module/lowmemorykiller/parameters/minfree" ``` 5. 触发AMS更新:发送配置变更广播,强制AMS调用`updateConfiguration()`: ```bash adb shell am broadcast -a android.intent.action.CONFIGURATION_CHANGED ``` - **注意事项**:修改是临时的(重启后失效),且需确保`adj`和`minfree`数组长度匹配。 ##### 方法二:通过AMS代码修改(系统开发者) 如果是AOSP(Android Open Source Project)开发,可在`ActivityManagerService.java`中调整: - **修改默认值**:编辑`updateOomLevels()`方法,调整`mOomAdj`数组的预设值。 - **自定义进程adj**:在`applyOomAdjLocked()`中,根据进程类型(如`ProcessList.HOME_APP_ADJ`)覆盖`oom_adj`计算逻辑。 - **触发更新**:在代码中调用`updateConfiguration()`,例如响应特定事件: ```java // 示例:在AMS中手动触发更新 mHandler.post(() -> updateConfiguration()); ``` #### 3. **注意事项与风险** - **权限要求**:写入sysfs或修改AMS代码需要root权限或系统签名权限,普通应用无法直接操作。 - **稳定性风险**:错误配置可能导致系统频繁杀死关键进程(如SystemUI),引发崩溃或ANR(Application Not Responding)。 - **版本兼容性**:不同Android版本中AMS实现可能变化(如Android 12引入Perceptible进程级别),需检查源码适配。 - **调试工具**:使用`adb shell cat /proc/<pid>/oom_score_adj` 验证进程的当前值,或`dumpsys activity oom` 查看系统OOM状态。 #### 4. **底层原理简述** 当AMS调用`updateConfiguration()`时: 1. 计算新`oom_adj`级别并写入sysfs。 2. lmkd守护进程读取参数,更新内核策略。 3. 内核shrinker机制在内存不足时,基于当前`oom_adj`和RSS(Resident Set Size)选择进程杀死[^4]。 例如,系统启动时首次配置变更会触发此流程[^2]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

私房菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值