low memory killer

low memory killer,第1张

low memory killer

1 android 作为移动设备的 *** 作系统,可能出现管理的内部不足的情况,为了尽量保证程序继续运行,需要有机制处理相关的内存问题。

2 Android *** 作系统是基于linux的,linux 系统具有缓存内存的功能,即为了加快下次的速度,打开文件后放到内存中,再关闭后不会自动释放掉该内存,所以是cache memory。 

会出现linux设备内存有多大,linux系统就会尽量多占用内存,减少下次启动的时间。再内存不够用的时候才会去释放。

Android 设备延用了linux的这个机制,但做了部分的优化,不是缓存文件等,而是缓存进程,但打开一个app后,会创建该app的进程,退出app时不会立刻关掉该进程,所以该进程会占用部分内存。这样的优点是加快下次打开apk的速度。

3  Linux 有oom的机制,在内存不足时释放以让当前程序跑下去。android 同样也有oom处理机制(low memory killer).

4 内存不足时,杀掉谁腾出内存空间是有定义一个rule, 正常理解肯定是先杀手无用的且占内存较大的进程,保证前台显示的进程正常使用。

如driver中有一个数组,

如下,当内存少爷16 * 1024 (64m)时会杀手adj > 12的进程。

kernel 4.12 之前lmk 在内核中

drivers/staging/android/lowmemorykiller.c

static u32 lowmem_debug_level = 1;
static short lowmem_adj[6] = {
    0,
    1,
    6,
    12,
};

static int lowmem_adj_size = 4;
static int lowmem_minfree[6] = {
    3 * 512,    
    2 * 1024,   
    4 * 1024,   
    16 * 1024,  
};

5  kernel 4.12之后lmk 已经在内核中删除,使用用户空间的lmkd 执行该功能。

https://source.android.com/devices/tech/perf/lmkd

Historically, Android monitored system memory pressure using an in-kernel low memory killer (LMK) driver, a rigid mechanism that depends on hard-coded values. As of kernel 4.12, the LMK driver is removed from the upstream kernel and the userspace lmkd performs memory monitoring and process killing tasks.

用户空间的lmkd的code路径

system/memory/lmkd/

https://source.android.com/devices/tech/perf/lmkd

6  android 定义了adj,lmkd就是根据这个adj值去判断杀手哪个进程, adj就是rule的体现。

如下面重要的process,有些adj值比较小,lmkd 一般不会杀掉,大的值lmkd就会有被杀手的风险。

/proc/1/oom_score_adj   值为-1000    --- NATIVE_ADJ

/proc/2/oom_score_adj   值为0    --- FOREGROUND_APP_ADJ

/proc/1571/oom_score_adj  值为-800  ---PERSISTENT_PROC_ADJ

/proc/1711/oom_score_adj 值为200   --- PERCEPTIBLE_APP_ADJ

/proc/4283/oom_score_adj  值为100   -- VISIBLE_APP_ADJ

/proc/1608/oom_score_adj 值为600    --- HOME_APP_ADJ

/proc/2846/oom_score_adj  值为700    -- PREVIOUS_APP_ADJ

/proc/5155/oom_score_adj  值为900   --- CACHED_APP_MIN_ADJ

这边定义得adj值

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

UNKNOWN_ADJ1001Undetermined adj, usually the process to be cachedCACHED_APP_MAX_ADJ999Maximum adj for invisible processesCACHED_APP_MIN_ADJ900Adj minimum for invisible processesSERVICE_B_ADJ800Compared with a list, the service in B list has a smaller adhesion to usersPREVIOUS_APP_ADJ700User’s previous interaction processHOME_APP_ADJ600Launcher processSERVICE_ADJ500Application service processHEAVY_WEIGHT_APP_ADJ400Heavyweight processes in the backgroundBACKUP_APP_ADJ300Processes that host backup related operationsPERCEPTIBLE_APP_ADJ200Perceptible processes, such as background music playbackVISIBLE_APP_ADJ100Activity process visible in the foregroundFOREGROUND_APP_ADJ0The process currently running in the foreground, that is, the program the user is interacting withPERSISTENT_SERVICE_ADJ-700Process bound to system process or persistent processPERSISTENT_PROC_ADJ-800The process of the persistent property, such as telephoneSYSTEM_ADJ-900System processNATIVE_ADJ-1000Native process, not managed by the system

7   android 提供方法,方便apk 和 bin档调整优先级,针对重要的apk或进程防止被lmk给杀掉。

android 如何设置adj

系统同时也会动态设置apk 的adj值,当打开一个apk,前台时 adj为FOREGROUND_APP_ADJ,  退出到后台adj就变成了PREVIOUS_APP_ADJ。

Android AMS的OomAdjuster 就是专门处理这个事情,有对四大组件activity/service/broadcast receiver/content provider分别根据不同的情况设置相应的adj值。

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

这边给了OOM调节的设计原理及主要功能

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

逻辑较多

    private boolean computeOomAdjLSP(ProcessRecord app, int cachedAdj,
            ProcessRecord topApp, boolean doingAll, long now, boolean cycleReeval,
            boolean computeClients) {

。。。。
        // important to least, and assign an appropriate OOM adjustment.
        int adj;
        int schedGroup;
        int procState;
        int cachedAdjSeq;
        int capability = 0;

        boolean foregroundActivities = false;
        boolean hasVisibleActivities = false;
        if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP && app == topApp) {
。。。
        } else if (state.isRunningRemoteAnimation()) {
。。。
        } else if (app.getActiveInstrumentation() != null) {
。。。
        } else if (state.getCachedIsReceivingBroadcast(mTmpBroadcastQueue)) {
。。。
        } else if (psr.numberOfExecutingServices() > 0) {

。。。
        } else if (app == topApp) {
。。。
        } else {
。。。
        }

。。。
        // Examine all activities if not already foreground.
        if (!foregroundActivities && state.getCachedHasActivities()) {
。。。
            schedGroup = state.getCachedSchedGroup();
        }

        if (procState > PROCESS_STATE_CACHED_RECENT && state.getCachedHasRecentTasks()) {
。。。
        }

        if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
                || procState > PROCESS_STATE_FOREGROUND_SERVICE) {
            if (psr.hasForegroundServices()) {
。。。
            } else if (state.hasOverlayUi()) {
。。。
            }
        }
        // If the app was recently in the foreground and moved to a foreground service status,
        // allow it to get a higher rank in memory for some time, compared to other foreground
        // services so that it can finish performing any persistence/processing of in-memory state.
        if (psr.hasForegroundServices() && adj > ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ
                && (state.getLastTopTime() + mConstants.TOP_TO_FGS_GRACE_DURATION > now
                || state.getSetProcState() <= PROCESS_STATE_TOP)) {
。。。
        }

        if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
                || procState > PROCESS_STATE_TRANSIENT_BACKGROUND) {
。。。
        }

        if (state.getCachedIsHeavyWeight()) {
。。。
        }

        if (state.getCachedIsHomeProcess()) {

。。。
        }

        if (state.getCachedIsPreviousProcess() && state.getCachedHasActivities()) {
。。。
        }
。。。
        for (int is = psr.numberOfRunningServices() - 1;
                is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                        || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                        || procState > PROCESS_STATE_TOP);
                is--) {
            ServiceRecord s = psr.getRunningServiceAt(is);
            if (s.startRequested) {
。。。
            }

。。。
        }

        final ProcessProviderRecord ppr = app.mProviders;
        for (int provi = ppr.numberOfProviders() - 1;
                provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                        || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                        || procState > PROCESS_STATE_TOP);
                provi--) {
            ContentProviderRecord cpr = ppr.getProviderAt(provi);
            for (int i = cpr.connections.size() - 1;
                    i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                            || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                            || procState > PROCESS_STATE_TOP);
                    i--) {
。。。
            }
。。。
        }
。。。


            if (s.isForeground) {

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5672003.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存