IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> android 修改adj的方法 -> 正文阅读

[移动开发]android 修改adj的方法

?android提供了low memory killer的机制在内存不足时回收内存。

?lmk 使用adj的方式判断该回收哪些进程或资源

android 修改adj的方法

先说结论:

A native side 统一由init进程设置/proc/**/oom_score_adj

B apk 统一由AMS 计算合适的adj,再交由lmkd 设置/proc/**/oom_score_adj

1 native side-- 直接写文档/proc/**/oom_score_adj

结论:所有的native bin档都是由init进程管理,并设置adj,默认是-1000,可以在**.rc中配置

A? ? init 进程

system/core/init/init.cpp

int SecondStageMain(int argc, char** argv) {

    ...

    // Set init and its forked children's oom_adj.
    if (auto result =
                WriteFile("/proc/1/oom_score_adj", StringPrintf("%d", DEFAULT_OOM_SCORE_ADJUST));
        !result.ok()) {
        LOG(ERROR) << "Unable to write " << DEFAULT_OOM_SCORE_ADJUST
                   << " to /proc/1/oom_score_adj: " << result.error();
    }

    ...
}

DEFAULT_OOM_SCORE_ADJUST 定义在lmkd_service.h中,值为-1000

system/core/init/lmkd_service.h

static const int MIN_OOM_SCORE_ADJUST = -1000;
static const int MAX_OOM_SCORE_ADJUST = 1000;
// service with default score is unkillable
static const int DEFAULT_OOM_SCORE_ADJUST = MIN_OOM_SCORE_ADJUST;

在环境中验证,就是-1000

console:/ # cat /proc/1/oom_score_adj
-1000

B? 其他native 进程

其他得native进程也是由init进程写得/proc/**/oom_score_adj, 如下面code所示

system/core/init/service.cpp

Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
                 const std::vector<gid_t>& supp_gids, int namespace_flags,
                 const std::string& seclabel, Subcontext* subcontext_for_restart_commands,
                 const std::vector<std::string>& args, bool from_apex)
    : ...
      oom_score_adjust_(DEFAULT_OOM_SCORE_ADJUST),
      ...


Result<void> Service::Start() {

    ...
    pid_t pid = -1;
    if (namespaces_.flags) {
        pid = clone(nullptr, nullptr, namespaces_.flags | SIGCHLD, nullptr);
    } else {
        pid = fork();
    }

    if (pid == 0) {
        ...
        _exit(127);
    }
    ...
    if (oom_score_adjust_ != DEFAULT_OOM_SCORE_ADJUST) {
        std::string oom_str = std::to_string(oom_score_adjust_);
        std::string oom_file = StringPrintf("/proc/%d/oom_score_adj", pid);
        if (!WriteStringToFile(oom_str, oom_file)) {
            PLOG(ERROR) << "couldn't write oom_score_adj";
        }
    }
    ...
}

该adj设置为oom_score_adjust_,默认值为DEFAULT_OOM_SCORE_ADJUST,是否可以自己配置吗?

答案是可以的

在init 中可以搜到如下code,?oom_score_adjust_是从rc档中parse出来的。

system/core/init/service_parser.cpp

Result<void> ServiceParser::ParseOomScoreAdjust(std::vector<std::string>&& args) {
    if (!ParseInt(args[1], &service_->oom_score_adjust_, MIN_OOM_SCORE_ADJUST,
                  MAX_OOM_SCORE_ADJUST)) {
        return Error() << "oom_score_adjust value must be in range " << MIN_OOM_SCORE_ADJUST
                       << " - +" << MAX_OOM_SCORE_ADJUST;
    }
    return {};
}

const KeywordMap<ServiceParser::OptionParser>& ServiceParser::GetParserMap() const {
    constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
    // clang-format off
    static const KeywordMap<ServiceParser::OptionParser> parser_map = {

        ...
        {"oom_score_adjust",        {1,     1,    &ServiceParser::ParseOomScoreAdjust}},
        ...
    }
}

从map的key value属性中可以看到,ParseOomScoreAdjust方法是对应的rc中的值为oom_score_adjust。没有设置的话,就是默认的-1000。

这样我们搜索oom_score_adjust定义的rc,就可以看到system/logging/logcat/logcatd.rc

这边定义的值是-600

# logcatd service
service logcatd /system/bin/logcatd -L -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r ${logd.logpersistd.rotate_kbytes:-2048} -n ${logd.logpersistd.size:-256} --id=${ro.build.id}
? ? class late_start
? ? disabled
? ? # logd for write to /data/misc/logd, log group for read from log daemon
? ? user logd
? ? group log
? ? writepid /dev/cpuset/system-background/tasks
? ? oom_score_adjust -600

查找rc的指导文件system/core/init/README.md?

`oom_score_adjust <value>`
> Sets the child's /proc/self/oom\_score\_adj to the specified value,
? which must range from -1000 to 1000.

2 apk 的adj值

apk 的adj值是根据AMS计算出来的。

在updateOomAdjLSP 会有很多的case,根据4大组件Activity, Service, Content Provider and Broadcast Receive。

具体的工作原理可以参考google 源码中的文档说明

frameworks/base/services/core/java/com/android/server/am/OomAdjuster.md

其中计算分数的说明部分,有很多的影响因子


* 如果不允许低于`ProcessList#FOREGROUND_APP_ADJ`,这意味着它可能是一个持久的进程,这里没有太多可做的。
* 检查进程是否为顶层应用,运行远程动画,运行检测,接收广播,执行服务,运行在顶层但睡眠(屏幕关闭),更新中间值。
* 询问窗口管理器(是的,ActivityTaskManager 现在与 WindowManager 一起)告诉每个活动的可见性信息。
* 检查进程是否有最近的任务,检查它是否正在托管前台服务、覆盖 UI、吐司等。 前台服务的注意事项,如果它处于前台状态,让它在内存中保持较高的等级一段时间:假设一个相机捕获案例,其中相机应用程序在切换出前景时仍在处理图片 - 保持它在内存中保持较高的等级将确保图片正确保留。
* 检查进程是否为重量级进程,其启动/退出会很慢,最好将其保存在内存中。请注意,整个系统中应该只有一个重量级进程。
* 当然,也不应该经常删除 Home 进程。
* 接下来的两个因素:对用户具有可见 UI 的前一个进程,或者是备份代理。
* 然后大量搜索连接服务service connection和内容提供商content provider,将对每个客户端进行评估,并且可以根据其客户端的分数更新自己 Oom Adj 分数。

所以最后一部分可以灵活调整apk的adj值了,

举一个例子将apk的adj设置为100

apk 调整adj的逻辑flow如下

frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java

frameworks/base/services/core/java/com/android/server/am/ProcessList.java

OomAdjuster.updateOomAdjLSP

????????OomAdjuster.updateOomAdjLSP

????????OomAdjuster.performUpdateOomAdjLSP

????????????????OomAdjuster.applyOomAdjLSP

????????????????????????ProcessList.setOomAdj

????????????????????????????????ProcessList.writeLmkd

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?LmkdConnection.exchange

????????????????????????????????????????????????LmkdConnection.write

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 通过socket 传递给lmkd


? ?lmkd 如下code中设置了/proc/%d/oom_score_adj

static void cmd_procprio(LMKD_CTRL_PACKET packet, int field_count, struct ucred *cred) {
    ...
    /* gid containing AID_READPROC required */
    /* CAP_SYS_RESOURCE required */
    /* CAP_DAC_OVERRIDE required */
    snprintf(path, sizeof(path), "/proc/%d/oom_score_adj", params.pid);
    snprintf(val, sizeof(val), "%d", params.oomadj);
    if (!writefilestring(path, val, false)) {
        ALOGW("Failed to open %s; errno=%d: process %d might have been killed",
              path, errno, params.pid);
        /* If this file does not exist the process is dead. */
        return;
    }
    ...
}

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-12-18 16:06:39  更:2021-12-18 16:08:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 8:28:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码