Android中进程管理



在android中,进程这个概念被淡化了,我们知道Android的每一个应用都是运行在一个独立的DVM中,他们之间互不影响;应用退出之后,并没有立马杀死进程,进程依然停留在内存中,这么做的目的是为了提高下次启动时的速度。而在Android中管理进程的模块是AMS,主要有LRU weight,OOM adj,Low Memory Killer共同来完成进程的管理。

1 LRU weight
LRU(最近最少使用)weight 主要用来衡量LRU的权重,在android进程启动之后,会以ProcessRecord类型的方式创建一个实例,保存到AMS的mLruProcesses变量中,mLurProcesses会以LRU的顺序来存储进程信息。当有一下情况时会更新mLruProcesses:
1.应用程序异常退出
2.调用AMS显式杀死进程
3.启动和调度四大组件
这里以启动和调度四大组件为例,它最终会调用AMS的updateLruProcessLock方法:
  1. final void updateLruProcessLocked(ProcessRecord app,  
  2.            boolean oomAdj, boolean updateActivityTime) {  
  3.        mLruSeq++;//lru序号加一  
  4.        updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);  
  5.    }  
先将LRU序号加一,用于标记一次更新LRU的操作,然后调用updateLruProcessInternalLocked:   
  1. private final void updateLruProcessInternalLocked(ProcessRecord app,  
  2.            boolean oomAdj, boolean updateActivityTime, int bestPos) {  
  3.        // put it on the LRU to keep track of when it should be exited.  
  4.        int lrui = mLruProcesses.indexOf(app);  
  5.        if (lrui >= 0) mLruProcesses.remove(lrui);  
  6.          
  7.        int i = mLruProcesses.size()-1;  
  8.        int skipTop = 0;  
  9.          
  10.        app.lruSeq = mLruSeq;  
  11.          
  12.        // compute the new weight for this process.  
  13.        if (updateActivityTime) {  
  14.            app.lastActivityTime = SystemClock.uptimeMillis();  
  15.        }  
  16.        if (app.activities.size() > 0) {  
  17.            // If this process has activities, we more strongly want to keep  
  18.            // it around.  
  19.            app.lruWeight = app.lastActivityTime;  
  20.        } else if (app.pubProviders.size() > 0) {  
  21.            // If this process contains content providers, we want to keep  
  22.            // it a little more strongly.  
  23.            app.lruWeight = app.lastActivityTime - ProcessList.CONTENT_APP_IDLE_OFFSET;  
  24.            // Also don't let it kick out the first few "real" hidden processes.  
  25.            skipTop = ProcessList.MIN_HIDDEN_APPS;  
  26.        } else {  
  27.            // If this process doesn't have activities, we less strongly  
  28.            // want to keep it around, and generally want to avoid getting  
  29.            // in front of any very recently used activities.  
  30.            app.lruWeight = app.lastActivityTime - ProcessList.EMPTY_APP_IDLE_OFFSET;  
  31.            // Also don't let it kick out the first few "real" hidden processes.  
  32.            skipTop = ProcessList.MIN_HIDDEN_APPS;  
  33.        }  
  34.          
  35.        while (i >= 0) {  
  36.            ProcessRecord p = mLruProcesses.get(i);  
  37.            // If this app shouldn't be in front of the first N background  
  38.            // apps, then skip over that many that are currently hidden.  
  39.            if (skipTop > 0 && p.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {  
  40.                skipTop--;  
  41.            }  
  42.            if (p.lruWeight <= app.lruWeight || i < bestPos) {  
  43.                mLruProcesses.add(i+1, app);//添加到mLruProcesses合适的位置  
  44.                break;  
  45.            }  
  46.            i--;  
  47.        }  
  48.        if (i < 0) {  
  49.            mLruProcesses.add(0, app);  
  50.        }  
  51.         // 如果这个进程之后总有cotent provider或者Service,重新计算  
  52.        // If the app is currently using a content provider or service,  
  53.        // bump those processes as well.  
  54.        if (app.connections.size() > 0) {  
  55.            for (ConnectionRecord cr : app.connections) {  
  56.                if (cr.binding != null && cr.binding.service != null  
  57.                        && cr.binding.service.app != null  
  58.                        && cr.binding.service.app.lruSeq != mLruSeq) {  
  59.                    updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,updateActivityTime, i+1);  
  60.                }  
  61.            }  
  62.        }  
  63.        if (app.conProviders.size() > 0) {  
  64.            for (ContentProviderRecord cpr : app.conProviders.keySet()) {  
  65.                if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq) {  
  66.                    updateLruProcessInternalLocked(cpr.proc, oomAdj,  
  67.                            updateActivityTime, i+1);  
  68.                }  
  69.            }  
  70.        }          
  71.        
  72.        if (oomAdj) {  
  73.            updateOomAdjLocked();调用updateOomAdjLocked 更新oom adj值  
  74.        }  
  75.    }  
这个函数主要作用
1.为该进程计算LRU序列号和LRU weight
2.根据计算出来的LRU weight,将该进程信息插入到mLRUProcesses合适的位置之中
3.如果该进程之中有content provider或者service,重新计算LRU weight
4.判断是否需要调用updateOomAdjLocked函数来更新oom adj的值

到此为止updateLruProcessLocked结束,可以看出,这个函数只是调整进程的LRU weight和在mLruProcesses中的位置,并没有直接参与进程的管理,真正参与进程管理的是updateOomAdjLocked函数,这个函数用来更新oom adj的值,这个值影响着进程的回收

2 OOM adj
OOM adj 定义了一系列的OOM的调整级别,从-17到15。在Low Memory Killer机制已经介绍过,这里看一下Android中定义了13个调整级别,在ProcessList文件中
  1. class ProcessList {  
  2.     // OOM adjustments for processes in various states:  
  3.   
  4.     // This is a process without anything currently running in it.  Definitely  
  5.     // the first to go! Value set in system/rootdir/init.rc on startup.  
  6.     // This value is initalized in the constructor, careful when refering to  
  7.     // this static variable externally.  
  8.     static final int EMPTY_APP_ADJ = 15;  
  9.   
  10.     // This is a process only hosting activities that are not visible,  
  11.     // so it can be killed without any disruption. Value set in  
  12.     // system/rootdir/init.rc on startup.  
  13.     static final int HIDDEN_APP_MAX_ADJ = 15;  
  14.     static int HIDDEN_APP_MIN_ADJ = 7;  
  15.   
  16.     // This is a process holding the home application -- we want to try  
  17.     // avoiding killing it, even if it would normally be in the background,  
  18.     // because the user interacts with it so much.  
  19.     static final int HOME_APP_ADJ = 6;  
  20.   
  21.     // This is a process holding a secondary server -- killing it will not  
  22.     // have much of an impact as far as the user is concerned. Value set in  
  23.     // system/rootdir/init.rc on startup.  
  24.     static final int SECONDARY_SERVER_ADJ = 5;  
  25.   
  26.     // This is a process currently hosting a backup operation.  Killing it  
  27.     // is not entirely fatal but is generally a bad idea.  
  28.     static final int BACKUP_APP_ADJ = 4;  
  29.   
  30.     // This is a process with a heavy-weight application.  It is in the  
  31.     // background, but we want to try to avoid killing it.  Value set in  
  32.     // system/rootdir/init.rc on startup.  
  33.     static final int HEAVY_WEIGHT_APP_ADJ = 3;  
  34.   
  35.     // This is a process only hosting components that are perceptible to the  
  36.     // user, and we really want to avoid killing them, but they are not  
  37.     // immediately visible. An example is background music playback.  Value set in  
  38.     // system/rootdir/init.rc on startup.  
  39.     static final int PERCEPTIBLE_APP_ADJ = 2;  
  40.   
  41.     // This is a process only hosting activities that are visible to the  
  42.     // user, so we'd prefer they don't disappear. Value set in  
  43.     // system/rootdir/init.rc on startup.  
  44.     static final int VISIBLE_APP_ADJ = 1;  
  45.   
  46.     // This is the process running the current foreground app.  We'd really  
  47.     // rather not kill it! Value set in system/rootdir/init.rc on startup.  
  48.     static final int FOREGROUND_APP_ADJ = 0;  
  49.   
  50.     // This is a process running a core server, such as telephony.  Definitely  
  51.     // don't want to kill it, but doing so is not completely fatal.  
  52.     static final int CORE_SERVER_ADJ = -12;  
  53.   
  54.     // The system process runs at the default adjustment.  
  55.     static final int SYSTEM_ADJ = -16;  
  56.      .....  
  57. }  
AMS提供了函数来改变这个值:updateOomAdjLocked    
  1. final void updateOomAdjLocked() {  
  2.        final ActivityRecord TOP_ACT = resumedAppLocked();  
  3.        final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;  
  4.   
  5.        if (false) {  
  6.            RuntimeException e = new RuntimeException();  
  7.            e.fillInStackTrace();  
  8.            Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);  
  9.        }  
  10.   
  11.        mAdjSeq++;  
  12.   
  13.        // Let's determine how many processes we have running vs.  
  14.        // how many slots we have for background processes; we may want  
  15.        // to put multiple processes in a slot of there are enough of  
  16.        // them.  
  17.        int numSlots = ProcessList.HIDDEN_APP_MAX_ADJ - ProcessList.HIDDEN_APP_MIN_ADJ + 1;  
  18.        int factor = (mLruProcesses.size()-4)/numSlots;  
  19.        if (factor < 1factor = 1;  
  20.        int step = 0;  
  21.        int numHidden = 0;  
  22.          
  23.        // First update the OOM adjustment for each of the  
  24.        // application processes based on their current state.  
  25.        int i = mLruProcesses.size();  
  26.        int curHiddenAdj = ProcessList.HIDDEN_APP_MIN_ADJ;  
  27.        int numBg = 0;  
  28.        while (i > 0) {  
  29.            i--;  
  30.            ProcessRecord app = mLruProcesses.get(i);  
  31.            //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);  
  32.             
  33.           //调用重载函数updateOomAdjLocked,更新OOM adj的值  
  34.            updateOomAdjLocked(app, curHiddenAdj, TOP_APP);  
  35.            if (curHiddenAdj < ProcessList.EMPTY_APP_ADJ  
  36.                && app.curAdj == curHiddenAdj) {  
  37.                step++;  
  38.                if (step >= factor) {  
  39.                    step = 0;  
  40.                    curHiddenAdj++;  
  41.                }  
  42.            }  
  43.            if (!app.killedBackground) {  
  44.                // 如果adj的值大于等于ProcessList.HIDDEN_APP_MIN_ADJ   
  45.                if (app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {  
  46.                    numHidden++;  
  47.                    if (numHidden > mProcessLimit) {  
  48.                        Slog.i(TAG, "No longer want " + app.processName  
  49.                                + " (pid " + app.pid + "): hidden #" + numHidden);  
  50.                        EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,  
  51.                                app.processName, app.setAdj, "too many background");  
  52.                        app.killedBackground = true;  
  53.                        Process.killProcessQuiet(app.pid);//杀死进程  
  54.                    } else {  
  55.                        numBg++;  
  56.                    }  
  57.                } else if (app.curAdj >= ProcessList.HOME_APP_ADJ) {  
  58.                    numBg++;  
  59.                }  
  60.            }  
  61.        }  
  62.     ......        
  63.    }  
其中调用了重载函数updateOomAdjLocked, 具体代码如下:
   
  1. private final boolean updateOomAdjLocked(ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {  
  2.        app.hiddenAdj = hiddenAdj;  
  3.   
  4.        if (app.thread == null) {  
  5.            return false;  
  6.        }  
  7.   
  8.        final boolean wasKeeping = app.keeping;  
  9.   
  10.        boolean success = true;  
  11.                
  12.        // 1调用computeOomAdjLocked方法计算oom adj的值   
  13.        computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);  
  14.   
  15.        if (app.curRawAdj != app.setRawAdj) {  
  16.            if (false) {  
  17.                // Removing for now.  Forcing GCs is not so useful anymore  
  18.                // with Dalvik, and the new memory level hint facility is  
  19.                // better for what we need to do these days.  
  20.                if (app.curRawAdj > ProcessList.FOREGROUND_APP_ADJ  
  21.                        && app.setRawAdj <= ProcessList.FOREGROUND_APP_ADJ) {  
  22.                    // If this app is transitioning from foreground to  
  23.                    // non-foreground, have it do a gc.  
  24.                    scheduleAppGcLocked(app);  
  25.                } else if (app.curRawAdj >= ProcessList.HIDDEN_APP_MIN_ADJ  
  26.                        && app.setRawAdj < ProcessList.HIDDEN_APP_MIN_ADJ) {  
  27.                    // Likewise do a gc when an app is moving in to the  
  28.                    // background (such as a service stopping).  
  29.                    scheduleAppGcLocked(app);  
  30.                }  
  31.            }  
  32.   
  33.            if (wasKeeping && !app.keeping) {  
  34.                // This app is no longer something we want to keep.  Note  
  35.                // its current wake lock time to later know to kill it if  
  36.                // it is not behaving well.  
  37.                BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();  
  38.                synchronized (stats) {  
  39.                    app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,  
  40.                            app.pid, SystemClock.elapsedRealtime());  
  41.                }  
  42.                app.lastCpuTime = app.curCpuTime;  
  43.            }  
  44.   
  45.            app.setRawAdj = app.curRawAdj;  
  46.        }  
  47.        if (app.curAdj != app.setAdj) {  
  48.            // 2  调用setOomAdj来修改进程的oom adj的值   
  49.            if (Process.setOomAdj(app.pid, app.curAdj)) {  
  50.                if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(  
  51.                    TAG, "Set app " + app.processName +  
  52.                    " oom adj to " + app.curAdj + " because " + app.adjType);  
  53.                app.setAdj = app.curAdj;  
  54.            } else {  
  55.                success = false;  
  56.                Slog.w(TAG, "Failed setting oom adj of " + app + " to " + app.curAdj);  
  57.            }  
  58.        }  
  59.        if (app.setSchedGroup != app.curSchedGroup) {  
  60.            app.setSchedGroup = app.curSchedGroup;  
  61.            if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,  
  62.                    "Setting process group of " + app.processName  
  63.                    + " to " + app.curSchedGroup);  
  64.            if (app.waitingToKill != null &&  
  65.                    app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {  
  66.                Slog.i(TAG, "Killing " + app.toShortString() + ": " + app.waitingToKill);  
  67.                EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,  
  68.                        app.processName, app.setAdj, app.waitingToKill);  
  69.               // 3 调用killProcessQuiet杀死进程   
  70.                Process.killProcessQuiet(app.pid);  
  71.                success = false;  
  72.            } else {  
  73.                if (true) {  
  74.                    long oldId = Binder.clearCallingIdentity();  
  75.                    try {  
  76.                         // 4调用setProcessGroup修改进程的调度组   
  77.                        Process.setProcessGroup(app.pid, app.curSchedGroup);  
  78.                    } catch (Exception e) {  
  79.                        Slog.w(TAG, "Failed setting process group of " + app.pid  
  80.                                + " to " + app.curSchedGroup);  
  81.                        e.printStackTrace();  
  82.                    } finally {  
  83.                        Binder.restoreCallingIdentity(oldId);  
  84.                    }  
  85.                } else {  
  86.                    if (app.thread != null) {  
  87.                        try {  
  88.                            app.thread.setSchedulingGroup(app.curSchedGroup);  
  89.                        } catch (RemoteException e) {  
  90.                        }  
  91.                    }  
  92.                }  
  93.            }  
  94.        }  
  95.        return success;  
  96.    }  
函数updateOomAdjLocked,更新OOM adj的值,这一部分的主要工作有:
1.调用computeOomAdjLocked方法计算oom adj的值,这个函数比较复杂,通过一系列的运算,计算出oom adj的值
2.调用setOomAdj来修改进程的oom adj的值,这个函数就是向进程的/proc/<pid>/oom_adj文件写入计算出来的oom adj值
3.调用killProcessQuiet杀死进程
4.调用setProcessGroup修改进程的调度组
这里主要看第三步killProcessQuiet,这个函数在Process.java文件中:
  1. public static final void killProcessQuiet(int pid) {  
  2.        sendSignalQuiet(pid, SIGNAL_KILL);  
  3.    }  
调用了 sendSignalQuiet函数,这是一个native函数:
  1. public static final native void sendSignalQuiet(int pid, int signal);  
对应的实现在android_util_Process.cpp文件中:
  1. void android_os_Process_sendSignalQuiet(JNIEnv* env, jobject clazz, jint pid, jint sig)  
  2. {  
  3.     if (pid > 0) {  
  4.         kill(pid, sig);//杀死进程  
  5.     }  
  6. }  
到此为止进程杀死了,这种方式是直接杀死进程的方式,同样android还提供了一个被动杀死进程的机制 Low Memory Killer机制

3 Low Memory Killer机制
这一机制的主要思想就是定义不同的oom adj级别,并为每一个级别指定最小剩余阈值。当内存中可用内存小于该阈值时,就杀死所有等于或者大于该级别的进程,这部分参看 Low Memory Killer机制

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值