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应用程序的时候,Android会为每个程序分配一个Linux用户ID,并设置相应的权限,这样其它应用程序就不能访问此应用程序所拥有的数据和资源了。
在 Linux 中,一个用户ID 识别一个给定用户;在 Android 上,一个用户ID 识别一个应用程序。应用程序在安装时被分配用户 ID,应用程序在设备上的存续期间内,用户ID 保持不变。
默认情况下,每个apk运行在它自己的Linux进程中。当需要执行应用程序中的代码时,Android会启动一个jvm,即一个新的进程来执行,因此不同的apk运行在相互隔离的环境中。
3.进程的组织
ProcessList.java
)和procState(定义在
ActivityManager.java
)。
3.1oom_adj
- 进程的oom_adj值由ActivityManagerService根据运行在进程里面的组件的状态来计算
- 进程的oom_adj值取值范围为[-16,15], oom_adj值越小,就不容易被杀死
- 内存紧张时, LMK基于oom_adj值来决定是否要回收一个进程
- ActivityManagerService和WindowManagerService在特定情况下也会进行进程回收
- 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
![](https://i-blog.csdnimg.cn/blog_migrate/7eca9fbc943572147f09166a8d553833.png)
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? *
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有三种基本状态:
- Active:处于屏幕前景(当前task的栈顶Activity处于Active状态),同一时刻只能有一个Activity处于Active状态;
- Paused状态:处于背景画面画面状态,失去了焦点,但依然是活动状态;
- stopped:不可见,但依然保持所有的状态和内存信息。
可以调用finish()结束处理Paused或者stopped状态的Activity。
3.5进程状态的转换
进程各种状态之间通过下列的函数调用转换:
void onCreate(Bundle savedInstanceState)
void onStart()
void onRestart()
void onResume()
void onPause()
void onStop()
void onDestroy()
转换过程如下图:
![](https://i-blog.csdnimg.cn/blog_migrate/4bf055eec05f49435a239c7003779c8b.png)
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的实现过程中依次会computeOomAdjLocked
和applyOomAdjLocked
。
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;
}
五参updateOomAdjLocked
;
无参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());
}
其中applyOomAdjLocked方法作用如下:
1.把curRawAdj值赋给setRawAdj2.把adj值
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());
}
...
}
其中涉及重要参数有:
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;
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);
- 当curCachedAdj != nextCachedAdj,且stepCached大于cachedFactor时
- 若进程procState不为14或15,则设置adj=curEmptyAdj(初始化=9);
- 当curEmptyAdj != nextEmptyAdj,且stepEmpty大于EmptyFactor时
则curEmptyAdj = nextEmptyAdj,(nextEmptyAdj加2,nextEmptyAdj上限为15);
- 当curEmptyAdj != nextEmptyAdj,且stepEmpty大于EmptyFactor时
- 当进程procState=14或15,则设置adj=curCachedAdj(初始化=9);
- 判断进程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操作;
- 当curProcState >=7, 且pendingUiClean =true时,判断trimMemoryLevel取值范围
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