Android系统进程优先级策略 ADJ

您所在的位置:网站首页 提升进程优先级 Android系统进程优先级策略 ADJ

Android系统进程优先级策略 ADJ

2023-10-07 08:05| 来源: 网络整理| 查看: 265

本篇文章是基于Android9.0来介绍Android系统关于进程的优先级是如何定义和管理的。

概述 1.进程

进程-Process 是程序的一个运行实例。通常会有唯一一个pid与之对应。但pid不是绝对唯一的,当进程死亡后pid会被回收给另外的进程使用。在Android世界里,App开发者很容易认为系统的四大组件就是进程的载体,实际上,它们不能算是完整的进程实例,最多只能算是进程的组成部分。由于Android系统框架中,系统对进程的创建和管理进行了封装,每当我们在启动四大组件Activity, BroadcastReceiver,ContentProvider,Service任意一个的时候,系统就会去检查该组件所在的进程是否已经存在,如果不存在,框架就会自动调用startProcessLocked函数去创建进程。当然一个app可以存在多个进程,多个app也可以运行在同一个进程下,我们可以通过Android:process来设置。

2.优先级

Android系统框架设计理念里是希望对用户很重要的进程尽可能的长期存活,以此来提高用户体验。我们知道Android app在启动的时候会去做很多事情,比如系统会检测该app进程是否存在,如果不存在则需要通知zygote进程去fork app进程,同时完成application信息的初始化工作。此时如果app的进程存在,那么就会省略这个步骤,直接快速唤起app。对于app来说也是一样,通过进程保活可以去实现更多的功能,但是如果所有的app不管有用没用的都存活下来了,系统的资源毕竟是有限的,系统内存很快就会枯竭而亡,这时就需要有合理地进程回收机制了。那么究竟该怎么回收进程呢?其实系统是根据各个app四大组件的状态来决定进程的优先级值adj。系统会根据一定的策略先去回收优先级最低的(同时也是adj值最大的),其次再回收优先级略低的,依次类推,直到回收了足够的系统资源,保证系统正常运转。

3.adj取值范围及含义 ADJ级别取值含义NATIVE_ADJ-1000native进程SYSTEM_ADJ-900仅指system_server进程PERSISTENT_PROC_ADJ-800系统persistent进程PERSISTENT_SERVICE_ADJ-700关联着系统或persistent进程FOREGROUND_APP_ADJ0前台进程VISIBLE_APP_ADJ100可见进程PERCEPTIBLE_APP_ADJ200可感知进程,比如后台音乐播放BACKUP_APP_ADJ300备份进程HEAVY_WEIGHT_APP_ADJ400重量级进程SERVICE_ADJ500服务进程HOME_APP_ADJ600Home进程PREVIOUS_APP_ADJ700上一个进程SERVICE_B_ADJ800B List中的ServiceCACHED_APP_MIN_ADJ900不可见进程的adj最小值CACHED_APP_MAX_ADJ906不可见进程的adj最大值

从Android 7.0开始,ADJ采用100、200、300;在这之前的版本ADJ采用数字1、2、3,这样的调整可以更进一步地细化进程的优先级,比如在VISIBLE_APP_ADJ(100)与PERCEPTIBLE_APP_ADJ(200)之间,可以有ADJ=101、102级别的进程。

关于进程的优先级可以通过如下的命令查看

adb shell cd /proc/pid/ oom_adj oom_score oom_score_adj cat oom_adj 0 表示前台进程FOREGROUND_APP_ADJ

省去lmk对oom_score_adj的计算过程,Android 7.0之前的版本,oom_score_adj= oom_adj * 1000/17; 而Android 7.0开始,oom_score_adj= oom_adj,不用再经过一次转换。

4.LowMemoryKiller

Android的Low Memory Killer基于Linux的OOM(Out Of Memory Killer)机制,在Linux中,内存是以页面为单位分配的,OOM的策略更多的是用于分配内存不足时触发,将得分最高的进程杀掉。而lmk则会每隔一段时间检查一次,当系统剩余可用内存较低时,便会触发杀进程的策略,根据不同的剩余内存档位来选择杀不同优先级的进程,而不是等到OOM时再来杀进程,真正OOM时系统可能已经处于异常状态,系统更希望的是未雨绸缪,在内存很低时来杀掉一些优先级较低的进程来保障后续操作的顺利进行。这里不详细说,接下来会有一篇关于Low Memory Killer的文章来详细介绍。 那么在哪里可以看到各个剩余内存档位呢?可以通过如下方式:

frameworks/base/services/core/java/com/android/server/am/ProcessList.java // These are the various interesting memory levels that we will give to // the OOM killer. Note that the OOM killer only supports 6 slots, so we // can't give it a different value for every possible kind of process. private final int[] mOomAdj = new int[] { FOREGROUND_APP_ADJ, VISIBLE_APP_ADJ, PERCEPTIBLE_APP_ADJ, BACKUP_APP_ADJ, CACHED_APP_MIN_ADJ, CACHED_APP_MAX_ADJ }; 从ProcessList.java中关于mOomAdj的定义及注释中我们可以发现, 系统一共定义了6个档位, 分别对应了上表格中列出的几种进程类型。 adb shell cat /sys/module/lowmemorykiller/parameters/adj 0,100,200,300,900,906 adj值对应如下: FOREGROUND_APP_ADJ(0) VISIBLE_APP_ADJ(100) PERCEPTIBLE_APP_ADJ(200) BACKUP_APP_ADJ(300) CACHED_APP_MIN_ADJ(900) CACHED_APP_MAX_ADJ(906) cat /sys/module/lowmemorykiller/parameters/minfree 18432,23040,27648,32256,85296,120640 由于一个page=4k,对应的换算公式是:value*4/1024,换算结果如下: 72M,90M,108M,126M,144M,180M 剩余内存值档位对应如下: FOREGROUND_APP_ADJ(72M) VISIBLE_APP_ADJ(90M) PERCEPTIBLE_APP_ADJ(108M) BACKUP_APP_ADJ(126M) CACHED_APP_MIN_ADJ(144M) CACHED_APP_MAX_ADJ(180M)

进程刚启动时ADJ等于INVALID_ADJ,当执行完attachApplication(),该该进程的curAdj和setAdj不相等,则会触发执行setOomAdj()将该进程的节点/proc/pid/oom_score_adj写入oomadj值。举例:当系统剩余空闲内存低于某阈值(比如140MB),则从ADJ大于或等于相应阈值(比如900)的进程中,选择ADJ值最大的进程,如果存在多个ADJ相同的进程,则选择内存最大的进程。 在updateOomLevels()过程,会根据手机屏幕尺寸或内存大小来调整scale,默认大多数手机内存都大于700MB,则scale等于1。对于64位手机,cached进程的阈值会更大些。

private void updateOomLevels(int displayWidth, int displayHeight, boolean write) { // Scale buckets from avail memory: at 300MB we use the lowest values to // 700MB or more for the top values. float scaleMem = ((float)(mTotalMemMb-350))/(700-350); ... // Scale buckets from screen size. int minSize = 480*800; // 384000 int maxSize = 1280*800; // 1024000 230400 870400 .264 float scaleDisp = ((float)(displayWidth*displayHeight)-minSize)/(maxSize-minSize); ... float scale = scaleMem > scaleDisp ? scaleMem : scaleDisp; if (scale < 0) scale = 0; else if (scale > 1) scale = 1; ... final boolean is64bit = Build.SUPPORTED_64_BIT_ABIS.length > 0; for (int i=0; i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3