基于Android7.0的进程模型与调度算法分析

1.Android源码查看与下载

关于源码的阅读,可以访问http://androidxref.com/https://android.googlesource.com/android / platform / build / android-7.0.0_r1来阅读系统源码。下载源码可以使用清华大学开源软件镜像站提供的Android 镜像:https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/ 。也可以使用该百度网盘地址下载:http://pan.baidu.com/s/1ngsZs,它提供了多个Android版本的的源码下载。

2.什么是进程

2.1传统进程

传统的进程是程序执行的载体,进程是正在执行的计算机程序的一个实例,它包含了程序的代码及其当前的活动,进程退出意味着应用的关闭。

2.2Android中的进程

在Android中,进程(process)的概念被弱化,在Android中进程知识一个运行组件的容器,当系统需要运行一个组件时,启动包含它的进程,当组件不在使用时,进程也会被关闭。例如一个APK文件中的两个service,可以运行在一个进程中,也可以运行在各自的进程中。Android官方开发网站的这篇文章:Processes and Threads 非常好的介绍了Android系统中进程相关的一些基本概念和重要知识。
2.3Android进程模型

在安装Android应用程序的时候,Android会为每个程序分配一个Linux用户ID,并设置相应的权限,这样其它应用程序就不能访问此应用程序所拥有的数据和资源了。

在 Linux 中,一个用户ID 识别一个给定用户;在 Android 上,一个用户ID 识别一个应用程序。应用程序在安装时被分配用户 ID,应用程序在设备上的存续期间内,用户ID 保持不变。

默认情况下,每个apk运行在它自己的Linux进程中。当需要执行应用程序中的代码时,Android会启动一个jvm,即一个新的进程来执行,因此不同的apk运行在相互隔离的环境中。

3.进程的组织

android进程有两个比较重要的状态值,即adj(定义在 ProcessList.java )和procState(定义在 ActivityManager.java )。

3.1oom_adj

定义在ProcessList.java文件,oom_adj划分为16级,从-17到16之间取值。adj值越大,优先级越低,adj<0的进程都是系统进程。在Android的lowmemroykiller机制中,会对于所有进程进行分类,对于每一类别的进程会有其oom_adj值的取值范围,oom_adj值越高则代表进程越不重要,在系统执行低杀操作时,会从oom_adj值越高的开始杀。

  1. 进程的oom_adj值由ActivityManagerService根据运行在进程里面的组件的状态来计算
  2. 进程的oom_adj值取值范围为[-16,15], oom_adj值越小,就不容易被杀死
  3. 内存紧张时, LMK基于oom_adj值来决定是否要回收一个进程
  4. ActivityManagerService和WindowManagerService在特定情况下也会进行进程回收
  5. LMK的进程回收策略:当系统内存小于i时,在oom_adj值大于等于j的进程中,选择一个oom_adj值最大并且消耗内存最多的进程来回收
 /**
632     * Set the out-of-memory badness adjustment for a process.
633     *
634     * @param pid The process identifier to set.
635     * @param uid The uid of the app
636     * @param amt Adjustment value -- lmkd allows -16 to +15.
637     *
638     * {@hide}
639     */
640    public static final void setOomAdj(int pid, int uid, int amt) {
641        if (amt == UNKNOWN_ADJ)
642            return;
643
644        long start = SystemClock.elapsedRealtime();
645        ByteBuffer buf = ByteBuffer.allocate(4 * 4);
646        buf.putInt(LMK_PROCPRIO);
647        buf.putInt(pid);
648        buf.putInt(uid);
649        buf.putInt(amt);
650        writeLmkd(buf);
651        long now = SystemClock.elapsedRealtime();
652        if ((now-start) > 250) {
653            Slog.w("ActivityManager", "SLOW OOM ADJ: " + (now-start) + "ms for pid " + pid
654                    + " = " + amt);
655        }
656    }
来源:http://androidxref.com/7.0.0_r1/xref/frameworks/base/services/core/java/com/android/server/am/ProcessList.java#640

系统lowmemeorykiller机制下对于进程的级别的以变量的形式定义在framework/base/core/java/com/android/server/am/ProcessList.java类中,可总结成下表:https://blog.csdn.net/tonyandroid1984/article/details/71038732

3.2process_state

定义在ActivityManager.java文件

 /** @hide Process does not exist. */
331    public static final int PROCESS_STATE_NONEXISTENT = -1;
332
333    /** @hide Process is a persistent system process. */
334    public static final int PROCESS_STATE_PERSISTENT = 0;
335
336    /** @hide Process is a persistent system process and is doing UI. */
337    public static final int PROCESS_STATE_PERSISTENT_UI = 1;
338
339    /** @hide Process is hosting the current top activities.  Note that this covers
340     * all activities that are visible to the user. */
341    public static final int PROCESS_STATE_TOP = 2;
342
343    /** @hide Process is hosting a foreground service due to a system binding. */
344    public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 3;
345
346    /** @hide Process is hosting a foreground service. */
347    public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4;
348
349    /** @hide Same as {@link #PROCESS_STATE_TOP} but while device is sleeping. */
350    public static final int PROCESS_STATE_TOP_SLEEPING = 5;
351
352    /** @hide Process is important to the user, and something they are aware of. */
353    public static final int PROCESS_STATE_IMPORTANT_FOREGROUND = 6;
354
355    /** @hide Process is important to the user, but not something they are aware of. */
356    public static final int PROCESS_STATE_IMPORTANT_BACKGROUND = 7;
357
358    /** @hide Process is in the background running a backup/restore operation. */
359    public static final int PROCESS_STATE_BACKUP = 8;
360
361    /** @hide Process is in the background, but it can't restore its state so we want
362     * to try to avoid killing it. */
363    public static final int PROCESS_STATE_HEAVY_WEIGHT = 9;
364
365    /** @hide Process is in the background running a service.  Unlike oom_adj, this level
366     * is used for both the normal running in background state and the executing
367     * operations state. */
368    public static final int PROCESS_STATE_SERVICE = 10;
369
370    /** @hide Process is in the background running a receiver.   Note that from the
371     * perspective of oom_adj receivers run at a higher foreground level, but for our
372     * prioritization here that is not necessary and putting them below services means
373     * many fewer changes in some process states as they receive broadcasts. */
374    public static final int PROCESS_STATE_RECEIVER = 11;
375
376    /** @hide Process is in the background but hosts the home activity. */
377    public static final int PROCESS_STATE_HOME = 12;
378
379    /** @hide Process is in the background but hosts the last shown activity. */
380    public static final int PROCESS_STATE_LAST_ACTIVITY = 13;
381
382    /** @hide Process is being cached for later use and contains activities. */
383    public static final int PROCESS_STATE_CACHED_ACTIVITY = 14;
384
385    /** @hide Process is being cached for later use and is a client of another cached
386     * process that contains activities. */
387    public static final int PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 15;
388
389    /** @hide Process is being cached for later use and is empty. */
390    public static final int PROCESS_STATE_CACHED_EMPTY = 16;
391
392    /** @hide The lowest process state number */
393    public static final int MIN_PROCESS_STATE = PROCESS_STATE_NONEXISTENT;
394
395    /** @hide The highest process state number */
396    public static final int MAX_PROCESS_STATE = PROCESS_STATE_CACHED_EMPTY;
397
398    /** @hide Should this process state be considered a background state? *

来源:http://androidxref.com/7.0.0_r1/xref/frameworks/base/core/java/android/app/ActivityManager.java#331

process_state划分18类,从-1到16之间取值。

3.3进程开启

1.我们通常会使用修改清单文件的android:process来达到多进程的目的。如果android:process的value值以冒号开头的话,那么该进程就是私有进程,如果是以其他字符开头,那么就是公有进程,这样拥有相同 ShareUID 的不同应用可以跑在同一进程里。 

2.通过JNI利用C/C++,调用fork()方法来生成子进程,一般开发者会利用这种方法来做一些daemon(守护进程)进程,来实现防杀保活等效果。

3.AMS中启动一个进程调用的是addAppLocked()方法,代码如下:

final ProcessResord addAppLocked(ApplicationInfo info, boolean isolated){
  ProcessRecord app;
   //isolated为true表示要启动一个新进程
  if(!isolated){ 
     app=getProcessResordLocked(info.processName,info.uid,true);                                                                                       
   }else{
     app=null;
   }
   if(app=null){
       //创建一个ProcessRecord对象
       app=newProcessRecordLocked(info,null,0);
       mProcessNames.put(info.processName,app.uid,app);
       if(isolated){
           mIsolatedProcesses.put(app.uid,app);
       }
       updateLruProcessLocked(app,false,null);
       updateOomAdjLocked();
   }
   .....
  if(app.thred==null&&mPersistentStartingProcesses.indexOf(app)<0){   
       mPersistentStartingProcesses.add(app);
       //启动进程
       startProcessLocked(app,"added application",app.processName   
        abiOverride,null /*entryPoint */,null /*entryPointArgs */);
  }
  return app;
}
addAppLocked()方法会根据参数参数isolated来决定是否启动一个新进程,如果isoated为true,即使系统中可能已经有一个同名的进程存在,也会再创建一个新锦成。getProcessRecordLocked()方法用来当前运行的进程列表查找进程。newProcessRecordLocked()方法用来创建一个ProcessRecord的数据结构。updateLruProcessLocked方法用来更新运行进程的状态,updateOomAdjLocked()方法用来更新进程的优先级,这两个方法是Process的管理核心。

注:ShareUID :
ShareUserId,在Android里面每个app都有一个唯一的linux user ID,则这样权限就被设置成该应用程序的文件只对该用户可见,只对该应用程序自身可见,而我们可以使他们对其他的应用程序可见,这会使我们用到SharedUserId,也就是让两个apk使用相同的userID,这样它们就可以看到对方的文件。为了节省资源,具有相同ID的apk也可以在相同的linux进程中进行(注意,并不是一定要在一个进程里面运行),共享一个虚拟机。

ShareUserId的作用,数据共享、调用其他程序资源。

3.4进程的状态

在安卓中,一共分为五种状态的进程:分别为activityprocess,visibleprocess,backgroundprocess,startedserviceprogress,backgroundprocess,emptyprocess,这五种状态,他们的优先等级由上至下:


一、这里的ActiveProcess这个进程状态的进程此时正处于活跃的状态,用户可以和它进行交互,可以说,此时进程正在运行,而且可以收到来自外界的消息。

二、VisibleProcess,这个进程是可见的进程,但此时的进程已经失去了与用户之间的交互的能力,也就是说大概是这种情况,当有一个弹出框出现在当前的窗台上,我们此时无法正常点击后边的窗体里的控件,但是我们又能明显的看到后边的窗体,这个时候进程就处于这个状态。

三、StartServiceProcess这个进程根据意思翻译过来就是开启Service服务进程,我们都知道Service进程我们是看不到的,但他确实在运行,这种进程的状态就是这样的,比刚才的VisibleProcess相比,他又失去了界面。

四、BackgroundProcess这个进程称之为后台进程,他和StartServiceProcess的区别在于有没有服务,对于background这个后台进程来说,已经没有了服务,而startServiceProcess这个进程是有服务的,差在了这里。

五、最后一个emptyProcess,这个就变成了空进程,空进程就更加悲哀了,他不但没有了服务。可以说他就剩下一台虚拟机了,对于安卓每个程序来说,这是标配,他就剩下这层了,当然他在等待有人再来召唤,这样他就可以以很快的速度恢复过来。


补充:ctivity lifecycle Activity有三种基本状态

  1. Active:处于屏幕前景(当前task的栈顶Activity处于Active状态),同一时刻只能有一个Activity处于Active状态;
  2. Paused状态:处于背景画面画面状态,失去了焦点,但依然是活动状态;
  3. stopped:不可见,但依然保持所有的状态和内存信息。

    可以调用finish()结束处理Paused或者stopped状态的Activity。

3.5进程状态的转换

进程各种状态之间通过下列的函数调用转换

void onCreate(Bundle savedInstanceState)
void onStart()
void onRestart()
void onResume()
void onPause()
void onStop()

void onDestroy()

转换过程如下图:

4.进程调度之adj算法

4.1核心方法

  • updateOomAdjLocked:更新adj,当目标进程为空,或者被杀则返回false;否则返回true;
  • computeOomAdjLocked:计算adj,返回计算后RawAdj值;
  • applyOomAdjLocked:应用adj,当需要杀掉目标进程则返回false;否则返回true。
  • 前面提到调整adj的3大护法,最为常见的方法便是computeOomAdjLocked,这也是其他各个方法在需要更新adj时会调用的方法,该方法有3个不同参数的同名方法,定义如下:
无参方法:updateOomAdjLocked()
一参方法:updateOomAdjLocked(ProcessRecord app)
五参方法:updateOomAdjLocked(ProcessRecord app, int cachedAdj,
    ProcessRecord TOP_APP, boolean doingAll, long now)

updateOomAdjLocked的实现过程中依次会computeOomAdjLockedapplyOomAdjLocked

4.2adj算法

ADJ算法,其核心也就是updateOomAdjLocked方法。

下面对updateOomAdjLocked的三种方法进行分析:

4.2.1 一参updateOomAdjLocked

final boolean updateOomAdjLocked(ProcessRecord app) {
    //获取栈顶的Activity
    final ActivityRecord TOP_ACT = resumedAppLocked();
    final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
    final boolean wasCached = app.cached;

    mAdjSeq++;

    //确保cachedAdj>=9
    final int cachedAdj = app.curRawAdj >= ProcessList.CACHED_APP_MIN_ADJ
            ? app.curRawAdj : ProcessList.UNKNOWN_ADJ;

    //执行五参updateOomAdjLocked【见小节4.2.2】
    boolean success = updateOomAdjLocked(app, cachedAdj, TOP_APP, false,
            SystemClock.uptimeMillis());

    //当app cached状态改变,或者curRawAdj=16,则执行无参数updateOomAdjLocked【见小节4.2.3】
    if (wasCached != app.cached || app.curRawAdj == ProcessList.UNKNOWN_ADJ) {
        updateOomAdjLocked();
    }
    return success;
}
该方法主要功能:
1.执行 五参updateOomAdjLocked
2.当app经过更新adj操作后,其cached状态改变(包括由cached变成非cached,或者非cached变成cached),或者curRawAdj=16,则执行 无参updateOomAdjLocked

4.2.2五参updateOomAdjLocked

private final boolean updateOomAdjLocked(ProcessRecord app, int cachedAdj,
        ProcessRecord TOP_APP, boolean doingAll, long now) {
    if (app.thread == null) {
        return false;
    }
    //通过计算adj和procState,判断进程所属状态,从而调整adj
        computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now);
    //
    return applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime());
}

来源:http://androidxref.com/7.0.0_r1/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#20404

其中applyOomAdjLocked方法作用如下:

1.把curRawAdj值赋给setRawAdj2.把adj值

2. 发送给lmkd守护过程
3.当app标志waitingToKill,且没有广播接收器运转在该过程,而且调度组为后台非交互组,则杀掉该过程,设置applyOomAdjLocked过程失败;
4.设置过程组信息
5.设置过程状态
6.实施pss统计操作,和计算下一次pss时间
7.设置过程状态转变;

4.2.3无参updateOomAdjLocked

final void updateOomAdjLocked() {
    //获取栈顶的Activity
    final ActivityRecord TOP_ACT = resumedAppLocked();
    final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
    final long now = SystemClock.uptimeMillis();
    final long nowElapsed = SystemClock.elapsedRealtime();
    final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
    final int N = mLruProcesses.size();

    //重置所有uid记录,把curProcState设置成16(空进程)
    for (int i=mActiveUids.size()-1; i>=0; i--) {
        final UidRecord uidRec = mActiveUids.valueAt(i);
        uidRec.reset();
    }

    mAdjSeq++;
    mNewNumServiceProcs = 0;
    mNewNumAServiceProcs = 0;

    final int emptyProcessLimit;
    final int cachedProcessLimit;
    // mProcessLimit默认值等于32,通过开发者选择可设置,或者厂商会自行调整
    if (mProcessLimit <= 0) {
        emptyProcessLimit = cachedProcessLimit = 0;
    } else if (mProcessLimit == 1) {
        emptyProcessLimit = 1;
        cachedProcessLimit = 0;
    } else {
        //则emptyProcessLimit = 16, cachedProcessLimit = 16
        emptyProcessLimit = ProcessList.computeEmptyProcessLimit(mProcessLimit);
        cachedProcessLimit = mProcessLimit - emptyProcessLimit;
    }

    //经过计算得 numSlots =3
    int numSlots = (ProcessList.CACHED_APP_MAX_ADJ
            - ProcessList.CACHED_APP_MIN_ADJ + 1) / 2;
    int numEmptyProcs = N - mNumNonCachedProcs - mNumCachedHiddenProcs;

    //确保空进程个数不大于cached进程数
    if (numEmptyProcs > cachedProcessLimit) {
        numEmptyProcs = cachedProcessLimit;
    }
    int emptyFactor = numEmptyProcs/numSlots;
    if (emptyFactor < 1) emptyFactor = 1;
    int cachedFactor = (mNumCachedHiddenProcs > 0 ? mNumCachedHiddenProcs : 1)/numSlots;
    if (cachedFactor < 1) cachedFactor = 1;
    int stepCached = 0;
    int stepEmpty = 0;
    int numCached = 0;
    int numEmpty = 0;
    int numTrimming = 0;

    mNumNonCachedProcs = 0;
    mNumCachedHiddenProcs = 0;

    //更新所有进程状态(基于当前状态)
    int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ;
    int nextCachedAdj = curCachedAdj+1;
    int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
    int nextEmptyAdj = curEmptyAdj+2;
    ProcessRecord selectedAppRecord = null;
    long serviceLastActivity = 0;
    int numBServices = 0;
    for (int i=N-1; i>=0; i--) {
        ProcessRecord app = mLruProcesses.get(i);
        if (mEnableBServicePropagation && app.serviceb
                && (app.curAdj == ProcessList.SERVICE_B_ADJ)) {
            numBServices++;
            for (int s = app.services.size() - 1; s >= 0; s--) {
                ServiceRecord sr = app.services.valueAt(s);
                //上次活跃时间距离现在小于5s,则不会迁移到BService
                if (SystemClock.uptimeMillis() - sr.lastActivity
                        < mMinBServiceAgingTime) {
                    continue;
                }
                if (serviceLastActivity == 0) {
                    serviceLastActivity = sr.lastActivity;
                    selectedAppRecord = app;
                //记录service上次活动时间最长的那个app
                } else if (sr.lastActivity < serviceLastActivity) {
                    serviceLastActivity = sr.lastActivity;
                    selectedAppRecord = app;
                }
            }
        }

        if (!app.killedByAm && app.thread != null) {
            app.procStateChanged = false;
            //计算app的adj值【见小节2.4】
            computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now);

            //当进程未分配adj的情况下,更新adj(cached和empty算法是相同的)
            if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
                switch (app.curProcState) {
                    case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
                    case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                        //当进程procState=14或15,则设置adj=9;
                        app.curRawAdj = curCachedAdj;
                        app.curAdj = app.modifyRawOomAdj(curCachedAdj);
                        //当前cacheadj不等于下一次cachedadj时
                        if (curCachedAdj != nextCachedAdj) {
                            stepCached++;
                            //当stepCached大于cachedFactor,则将nextCachedAdj赋值给curCachedAdj,并且nextCachedAdj加2,nextCachedAdj最大等于15;
                            if (stepCached >= cachedFactor) {
                                stepCached = 0;
                                curCachedAdj = nextCachedAdj;
                                nextCachedAdj += 2;
                                if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
                                    nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
                                }
                            }
                        }
                        break;
                    default:
                        app.curRawAdj = curEmptyAdj;
                        app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
                        //更新curCachedAdj值
                        if (curEmptyAdj != nextEmptyAdj) {
                            stepEmpty++;
                            //当stepEmpty大于emptyFactor,则将nextEmptyAdj赋值给curEmptyAdj,并且nextEmptyAdj加2,nextEmptyAdj最大等于15;
                            if (stepEmpty >= emptyFactor) {
                                stepEmpty = 0;
                                curEmptyAdj = nextEmptyAdj;
                                nextEmptyAdj += 2;
                                if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
                                    nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
                                }
                            }
                        }
                        break;
                }
            }

            //【见小节2.5】
            applyOomAdjLocked(app, true, now, nowElapsed);

            //根据当前进程procState状态来决策
            switch (app.curProcState) {
                case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
                case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                    mNumCachedHiddenProcs++;
                    numCached++;
                    // 当cached进程超过上限(cachedProcessLimit),则杀掉该进程
                    if (numCached > cachedProcessLimit) {
                        app.kill("cached #" + numCached, true);
                    }
                    break;
                case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
                    // 当空进程超过上限(TRIM_EMPTY_APPS),且空闲时间超过30分钟,则杀掉该进程
                    if (numEmpty > ProcessList.TRIM_EMPTY_APPS
                            && app.lastActivityTime < oldTime) {
                        app.kill("empty for "
                                + ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime)
                                / 1000) + "s", true);
                    } else {
                        // 当空进程超过上限(emptyProcessLimit),则杀掉该进程
                        numEmpty++;
                        if (numEmpty > emptyProcessLimit) {
                            if (!CT_PROTECTED_PROCESS.equals(app.processName))
                                app.kill("empty #" + numEmpty, true);
                        }
                    }
                    break;
                default:
                    mNumNonCachedProcs++;
                    break;
            }

            if (app.isolated && app.services.size() <= 0) {
                //没有services运行的孤立进程,则直接杀掉
                app.kill("isolated not needed", true);
            } else {
                final UidRecord uidRec = app.uidRecord;
                if (uidRec != null && uidRec.curProcState > app.curProcState) {
                    uidRec.curProcState = app.curProcState;
                }
            }

            if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
                    && !app.killedByAm) {
                numTrimming++;
            }
        }
    }

    //当BServices个数超过上限(mBServiceAppThreshold),则
    if ((numBServices > mBServiceAppThreshold) && (true == mAllowLowerMemLevel)
            && (selectedAppRecord != null)) {
        ProcessList.setOomAdj(selectedAppRecord.pid, selectedAppRecord.info.uid,
                ProcessList.CACHED_APP_MAX_ADJ);
        selectedAppRecord.setAdj = selectedAppRecord.curAdj;
    }
    mNumServiceProcs = mNewNumServiceProcs;

    //根据CachedAndEmpty个数来调整内存因子memFactor
    final int numCachedAndEmpty = numCached + numEmpty;
    int memFactor;
    if (numCached <= ProcessList.TRIM_CACHED_APPS
            && numEmpty <= ProcessList.TRIM_EMPTY_APPS) {
        if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
            memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
        } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
            memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
        } else {
            memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
        }
    } else {
        memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
    }

    if (memFactor > mLastMemoryLevel) {
        if (!mAllowLowerMemLevel || mLruProcesses.size() >= mLastNumProcesses) {
            memFactor = mLastMemoryLevel;
        }
    }
    mLastMemoryLevel = memFactor;
    mLastNumProcesses = mLruProcesses.size();
    boolean allChanged = mProcessStats.setMemFactorLocked(memFactor, !isSleeping(), now);
    final int trackerMemFactor = mProcessStats.getMemFactorLocked();
    //当内存因子不是普通0级别的情况下
    if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
        if (mLowRamStartTime == 0) {
            mLowRamStartTime = now;
        }
        int step = 0;
        int fgTrimLevel;
        switch (memFactor) {
            case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
                fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
                break;
            case ProcessStats.ADJ_MEM_FACTOR_LOW:
                fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
                break;
            default:
                fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
                break;
        }
        int factor = numTrimming/3;
        int minFactor = 2;
        if (mHomeProcess != null) minFactor++;
        if (mPreviousProcess != null) minFactor++;
        if (factor < minFactor) factor = minFactor;

        //TRIM_MEMORY_COMPLETE:该进程处于LRU队列的尾部,当进程不足则会杀掉该进程
        int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
        for (int i=N-1; i>=0; i--) {
            ProcessRecord app = mLruProcesses.get(i);
            if (allChanged || app.procStateChanged) {
                setProcessTrackerStateLocked(app, trackerMemFactor, now);
                app.procStateChanged = false;
            }
            //当curProcState > 12且没有被am杀掉的情况;
            if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
                    && !app.killedByAm) {
                if (app.trimMemoryLevel < curLevel && app.thread != null) {
                    //调度app执行trim memory的操作
                    app.thread.scheduleTrimMemory(curLevel);
                }
                app.trimMemoryLevel = curLevel;
                step++;
                if (step >= factor) {
                    step = 0;
                    switch (curLevel) {
                        case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
                            curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
                            break;
                        case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
                            curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
                            break;
                    }
                }
            } else if (app.curProcState == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
                if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
                        && app.thread != null) {
                    app.thread.scheduleTrimMemory(
                            ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
                }
                app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
            } else {
                if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
                        || app.systemNoUi) && app.pendingUiClean) {
                    final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
                    if (app.trimMemoryLevel < level && app.thread != null) {
                        app.thread.scheduleTrimMemory(level);
                    }
                    app.pendingUiClean = false;
                }
                if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
                    app.thread.scheduleTrimMemory(fgTrimLevel);
                }
                app.trimMemoryLevel = fgTrimLevel;
            }
        }
    } else {
        if (mLowRamStartTime != 0) {
            mLowRamTimeSinceLastIdle += now - mLowRamStartTime;
            mLowRamStartTime = 0;
        }
        for (int i=N-1; i>=0; i--) {
            ProcessRecord app = mLruProcesses.get(i);
            if (allChanged || app.procStateChanged) {
                setProcessTrackerStateLocked(app, trackerMemFactor, now);
                app.procStateChanged = false;
            }
            if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
                    || app.systemNoUi) && app.pendingUiClean) {
                if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
                        && app.thread != null) {
                    app.thread.scheduleTrimMemory(
                            ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
                }
                app.pendingUiClean = false;
            }
            app.trimMemoryLevel = 0;
        }
    }

    //是否finish activity
    if (mAlwaysFinishActivities) {
        mStackSupervisor.scheduleDestroyAllActivities(null, "always-finish");
    }

    if (allChanged) {
        requestPssAllProcsLocked(now, false, mProcessStats.isMemFactorLowered());
    }
    ...
}

来源:http://androidxref.com/7.0.0_r1/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#20500

其中涉及重要参数有:

49      // We allow empty processes to stick around for at most 30 minutes.
         //空进程存活时长: MAX_EMPTY_TIME = 30min
150    static final long MAX_EMPTY_TIME = 30*60*1000;
151
152    // The maximum number of empty app processes we will let sit around.
         //空进程个数上限:MAX_EMPTY_APPS = computeEmptyProcessLimit(MAX_CACHED_APPS) = MAX_CACHED_APPS/2 = 16
153    private static final int MAX_EMPTY_APPS = computeEmptyProcessLimit(MAX_CACHED_APPS);
154
155     // The number of empty apps at which we don't consider it necessary to do
156    // memory trimming.
         //trim空进程个数上限:TRIM_EMPTY_APPS = computeTrimEmptyApps() = MAX_EMPTY_APPS/2 = 8;
157    static final int TRIM_EMPTY_APPS = MAX_EMPTY_APPS/2;
158
159    // The number of cached at which we don't consider it necessary to do
160    // memory trimming.
        //trim缓存进程个数上限:TRIM_CACHED_APPS = computeTrimCachedApps() = MAX_CACHED_APPS-MAX_EMPTY_APPS)/3 = 5;
161    static final int TRIM_CACHED_APPS = (MAX_CACHED_APPS-MAX_EMPTY_APPS)/3;
162
163    // Threshold of number of cached+empty where we consider memory critical.
164    static final int TRIM_CRITICAL_THRESHOLD = 3;
165
166    // Threshold of number of cached+empty where we consider memory critical.
167    static final int TRIM_LOW_THRESHOLD = 5;

来源:http://androidxref.com/7.0.0_r1/xref/frameworks/base/services/core/java/com/android/server/am/ProcessList.java#149

mBServiceAppThreshold = SystemProperties.getInt(“ro.sys.fw.bservice_limit”, 5);
mMinBServiceAgingTime =SystemProperties.getInt(“ro.sys.fw.bservice_age”, 5000);
mProcessLimit = ProcessList.MAX_CACHED_APPS
mProcessLimit = emptyProcessLimit(空进程上限) + cachedProcessLimit(缓存进程上限)
oldTime = now – ProcessList.MAX_EMPTY_TIME;
LRU进程队列长度 = numEmptyProcs(空进程数) + mNumCachedHiddenProcs(cached进程) + mNumNonCachedProcs(非cached进程)
emptyFactor = numEmptyProcs/3, 且大于等于1
cachedFactor = mNumCachedHiddenProcs/3, 且大于等于1

4.2.4对updateOomAdjLocked方法小结

updateOomAdjLocked过程比较复杂,主要分为更新adj(满足条件则杀进程)和根据memFactor来调度执行TrimMemory操作;

第一部分:更新adj(满足条件则杀进程)

  • 遍历mLruProcesses进程,检查进程是否分配了adj
    • 若未分配
      • 当进程procState=14或15,则设置adj=curCachedAdj(初始化=9);
        • 当curCachedAdj != nextCachedAdj,且stepCached大于cachedFactor时
          令curCachedAdj = nextCachedAdj,(nextCachedAdj加2,nextCachedAdj上限为15);
      • 若进程procState不为14或15,则设置adj=curEmptyAdj(初始化=9);
        • 当curEmptyAdj != nextEmptyAdj,且stepEmpty大于EmptyFactor时
          则curEmptyAdj = nextEmptyAdj,(nextEmptyAdj加2,nextEmptyAdj上限为15);
    • 判断进程procState状态:
      • 当curProcState=14或15,且cached进程超过上限(cachedProcessLimit=32)时,杀掉该进程
      • 当curProcState=16的时,判断空进程超过何种上限:
        • 若超过上限(TRIM_EMPTY_APPS=8),且空闲时间超过30分钟,则杀掉该进程
        • 否则,当空进程超过上限(emptyProcessLimit=16),则杀掉该进程
    • 最后,若为没有services运行的孤立进程,则杀掉该进程;

第二部分:根据memFactor来调度执行TrimMemory操作;

  • 根据CachedAndEmpty个数来调整内存因子memFactor(值越大,级别越高):
    • 当CachedAndEmpty < 3时,令memFactor=3;
    • 当CachedAndEmpty < 5时,令则memFactor=2;
    • 当CachedAndEmpty >=5时,令且numCached<=5,numEmpty<=8,则memFactor=1;
    • 当numCached>5 或numEmpty>8,则memFactor=0;
  • 若内存因子不是普通0级别,根据memFactor来调整前台trim级别(fgTrimLevel):
    • 当memFactor=3时,令fgTrimLevel=TRIM_MEMORY_RUNNING_CRITICAL;
    • 当memFactor=2时,令fgTrimLevel=TRIM_MEMORY_RUNNING_LOW;
    • 否则(就是memFactor=1),令fgTrimLevel=TRIM_MEMORY_RUNNING_MODERATE
    • 再遍历mLruProcesses队列进程:
      • 当curProcState > 12且没有被am杀掉时,执行TrimMemory操作;
      • 当curProcState = 9 且trimMemoryLevel<TRIM_MEMORY_BACKGROUND时,执行TrimMemory操作;
      • 当curProcState > 7且pendingUiClean =true时,判断trimMemoryLevel大小
        • 若trimMemoryLevel<TRIM_MEMORY_UI_HIDDEN,则执行TrimMemory操作;
        • 若trimMemoryLevel<fgTrimLevel,则执行TrimMemory操作;
  • 当内存因子等于0的情况下,遍历mLruProcesses队列进程:
    • 当curProcState >=7, 且pendingUiClean =true时,判断trimMemoryLevel取值范围
      • 当trimMemoryLevel< TRIM_MEMORY_UI_HIDDEN时,执行TrimMemory操作;

5.对操作系统进程模型的看法

安卓操作系统与linux操作系统有一些相同的地方,比如在安装Android应用程序的时候,Android会为每个程序分配一个Linux用户ID,两者在开启一个新进程是均是调用fork()方法但是不同之处更多,在 Linux 中,一个用户ID 识别一个给定用户;在 Android 上,一个用户ID 识别一个应用程序。应用程序在安装时被分配用户 ID,应用程序在设备上的存续期间内,用户ID 保持不变。默认情况下,每个apk运行在它自己的Linux进程中。当需要执行应用程序中的代码时,Android会启动一个jvm,即一个新的进程来执行,因此不同的apk运行在相互隔离的环境中。

默认情况下,Android为每个应用程序创建一个单独的进程,所有组件运行在该进程中,这个默认进程的名字通常与该应用程序的包名相同。当应用的第一个组件需要被执行时,Android Framework会为此启动一个有单线程(主线程,即UI线程)运行环境的Linux进程。当Android系统资源紧缺时会终止一些进程的执行。对于特定的Android组件<activity> <service> <receiver> <provider>,我们可以通过android:process来指定它运行的:进程每个组件可以运行在它所指定的进程中;一些组件会共享一个进程, 而其他的不在其中;不同application中的组件可以在同一个进程中执行。我们可以通过设置<application>的process属性指定应用所有组件的默认运行进程

另外当我们按下home键或者返回键后进程不会被销毁,当然根据安卓虚拟机的垃圾回收机制,如果赶上当前资源匮乏,可能就要牺牲这个进程,因为当前来说,这个进程是优先级最低的。

6.参考资料

1.https://blog.csdn.net/Simon_Crystin/article/details/70315106

2.https://blog.csdn.net/linliang815/article/details/77000630

3.https://www.cnblogs.com/xiatianyu/p/Android_Process_Status.html

4.https://yq.aliyun.com/articles/456006

5.https://www.cnblogs.com/tiger-wang-ms/p/6491429.html

6.http://www.apkbus.com/blog-705730-61527.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值