AMS的进程管理
Android将应用进程分为五大类,分别为Forground类、Visible类、Service类、Background类及Empty类。这五大类划分各有规则。
Forground类进程
该类进程重要性最高,想成为这一类进程需要满足下面的属性:
1.含有一个前端的Activity(OnResume函数被调用过了,或者说当前正在显示的那个Activity)
2.含有一个与前端Activity bind 的Service
3.含有一个调用了startForground的Service,或者该进程的Service正在调用其生命周期的函数(onCreate、onStart、onDestroy)
4.该进程含有一个BroadcastReceiver实例并且正在执行onReceive函数
Visible类进程
这类进程没有处于前端的组件,但是用户仍然能看到它们,此类进程包括两种:
1.含有一个仅onPause被调用的Activity(即它还在前台,只不过部分界面被遮住)
2.包含一个Service,并且该Service和一个Visible的Activity绑定
Service类进程: 该类进程包含一个Service,此Service通过startService启动,并且不属于前面两类进程,如MediaScannerService。
Background进程: 包含当前不可见的Activity(onStop被调用过),系统保存这些进程到一个LRU(最近最少使用)列表,当系统需要内存时,LRU里的进程将被杀死。
Empty进程: 不包含任何组件,系统保留它们仅仅是当需要的时候为了省去fork进程,创建Android运行环境等一系列漫长而艰苦的工作。
其实Android对于进程的划分是根据oom_adj值来划分的,种类也多得多,Android是通过设置进程的oom_adj值来进行进程的调度的(kernel在OOM情况下会根据进程的oom_adj值来选择杀死一些进程)。其中Android在linux的下新增了一个LMK(low memory killer)的工作方式。LMK的职责是根据当前内存大小去杀死对应oom_adj及以上的进程以回收内存。这里就对应关键的参数,即不同内存的阈值及oom_adj。
Android平台进程调度和OOM控制的API,它们统一被封装在Process.java中,关键代码如下:
1 //设置线程的调度优先级 2 public static final native void setThreadPriority(int tid, int priority) 3 throws IllegalArgumentException, SecurityException; 4 //设置线程的Group,实际上就是设置线程的调度策略 5 public static final native void setThreadGroup(int tid, int group) 6 throws IllegalArgumentException, SecurityException; 7 //设置进程的调度策略,包括该进程的所有线程 8 public static final native void setProcessGroup(int pid, int group) 9 throws IllegalArgumentException, SecurityException; 10 //调整进程的oom_adj值 11 public static final native boolean setOomAdj(int pid, int amt);
下面是ProcessList类中对oom_adj,我们可以看到Android对进程的详细分类。
1 // OOM adjustments for processes in various states: 2 3 // Adjustment used in certain places where we don't know it yet. 4 // (Generally this is something that is going to be cached, but we 5 // don't know the exact value in the cached range to assign yet.) 6 static final int UNKNOWN_ADJ = 16; 7 8 // This is a process only hosting activities that are not visible, 9 // so it can be killed without any disruption. 10 static final int CACHED_APP_MAX_ADJ = 15; 11 static final int CACHED_APP_MIN_ADJ = 9; 12 13 // The B list of SERVICE_ADJ -- these are the old and decrepit 14 // services that aren't as shiny and interesting as the ones in the A list. 15 static final int SERVICE_B_ADJ = 8; 16 17 // This is the process of the previous application that the user was in. 18 // This process is kept above other things, because it is very common to 19 // switch back to the previous app. This is important both for recent 20 // task switch (toggling between the two top recent apps) as well as normal 21 // UI flow such as clicking on a URI in the e-mail app to view in the browser, 22 // and then pressing back to return to e-mail. 23 static final int PREVIOUS_APP_ADJ = 7; 24 25 // This is a process holding the home application -- we want to try 26 // avoiding killing it, even if it would normally be in the background, 27 // because the user interacts with it so much. 28 static final int HOME_APP_ADJ = 6; 29 30 // This is a process holding an application service -- killing it will not 31 // have much of an impact as far as the user is concerned. 32 static final int SERVICE_ADJ = 5; 33 34 // This is a process with a heavy-weight application. It is in the 35 // background, but we want to try to avoid killing it. Value set in 36 // system/rootdir/init.rc on startup. 37 static final int HEAVY_WEIGHT_APP_ADJ = 4; 38 39 // This is a process currently hosting a backup operation. Killing it 40 // is not entirely fatal but is generally a bad idea. 41 static final int BACKUP_APP_ADJ = 3; 42 43 // This is a process only hosting components that are perceptible to the 44 // user, and we really want to avoid killing them, but they are not 45 // immediately visible. An example is background music playback. 46 static final int PERCEPTIBLE_APP_ADJ = 2; 47 48 // This is a process only hosting activities that are visible to the 49 // user, so we'd prefer they don't disappear. 50 static final int VISIBLE_APP_ADJ = 1; 51 52 // This is the process running the current foreground app. We'd really 53 // rather not kill it! 54 static final int FOREGROUND_APP_ADJ = 0; 55 56 // This is a process that the system or a persistent process has bound to, 57 // and indicated it is important. 58 static final int PERSISTENT_SERVICE_ADJ = -11; 59 60 // This is a system persistent process, such as telephony. Definitely 61 // don't want to kill it, but doing so is not completely fatal. 62 static final int PERSISTENT_PROC_ADJ = -12; 63 64 // The system process runs at the default adjustment. 65 static final int SYSTEM_ADJ = -16; 66 67 // Special code for native processes that are not being managed by the system (so 68 // don't have an oom adj assigned by the system). 69 static final int NATIVE_ADJ = -17;
不同内存手机的阈值也被定义在ProcessList中:
1 //LMK设置的六个oom_adj 2 private final int[] mOomAdj = new int[] { 3 FOREGROUND_APP_ADJ, VISIBLE_APP_ADJ, PERCEPTIBLE_APP_ADJ, 4 BACKUP_APP_ADJ, CACHED_APP_MIN_ADJ, CACHED_APP_MAX_ADJ 5 }; 6 // These are the low-end OOM level limits. This is appropriate for an 7 // HVGA or smaller phone with less than 512MB. Values are in KB. 8 private final int[] mOomMinFreeLow = new int[] { 9 12288, 18432, 24576, 10 36864, 43008, 49152 11 }; 12 // These are the high-end OOM level limits. This is appropriate for a 13 // 1280x800 or larger screen with around 1GB RAM. Values are in KB. 14 private static final int[] mOomMinFreeHigh = new int[] { 15 73728, 92160, 110592, 16 129024, 147456, 184320 17 };
另外在ProcessRecord中也定义了较多成员用于进程管理,就不列出来了。
下面就是AMS进程管理函数的分析了。
在AMS中,主要是两个函数来管理进程。分别为:updateLruProcessLocked 和 updateOomAdjLocked。
updateLruProcessLocked
Android所有应用进程(包括system_server)的ProcessRecord信息都保存在mPidsSelfLocked成员中,除此之外还有一个成员变量mLruProcesses也用于保存ProcessRecord。mLruProcesses的类型虽然是ArrayList,但其内部成员却是按照ProcessRecord的lruWeight大小排序的。在运行过程中,AMS会根据lruWeight的变化调整mLruProcesses成员的位置。updateLruProcessLocked的主要工作是根据app的lruWeight值调整它在数组中的位置。lruWeight越大,其在数组中的位置就越靠后。如果该app和某些Service或ContentProvider有交互关系,那就连同这些Service或ContentProvider所在进程调节lruWeight值。
updateOomAdjLocked
在updateOomAdjLocked函数中,AMS做了比较多事,都是为了最终调用computeOomAdjLocked函数计算某个进程的oom_adj和调度策略来完成对应用进程的管理,这之间4.0增加了一个接口类ComponentCallbacks2,定义了一个函数onTrimMemory,主要通知应用进程进行一定的内存释放。AMS的进程管理核心还是在computeOomAdjLocked里,computeOomAdjLocked就是一个算法,就是根据各种情况来设置几个值,这个调整的算法改进变动的可能性还是比较大的。Android在什么情况下会进行进程的调度呢?
1 bindBackupAgent(ApplicationInfo ,int ) 2 bindService(IApplicationThread,Ibinder,Intent,String,IService) 3 bringDownServiceLocked(ServiceRecord,boolean) 4 getContentProviderImpl(IApplicationThread,String) 5 publishContentProviders() 6 removeConnectionLocked()
...