android 优先级更新
APP中很多操作都可能会影响进程列表的优先级,比如退到后台、移到前台等,都会潜在的影响进程的优先级,我们知道Lowmemorykiller是通过遍历内核的进程结构体队列,选择优先级低的杀死,那么APP操作是如何写入到内核空间的呢?Linxu有用户间跟内核空间的区分,无论是APP还是系统服务,都是运行在用户空间,严格说用户控件的操作是无法直接影响内核空间的,更不用说更改进程的优先级。其实这里是通过了Linux中的一个proc文件体统,proc文件系统可以简单的看多是内核空间映射成用户可以操作的文件系统,当然不是所有进程都有权利操作,通过proc文件系统,用户空间的进程就能够修改内核空间的数据,比如修改进程的优先级,在Android家族,5.0之前的系统是AMS进程直接修改的,5.0之后,是修改优先级的操作被封装成了一个独立的服务-lmkd,lmkd服务位于用户空间,其作用层次同AMS、WMS类似,就是一个普通的系统服务。我们先看一下5.0之前的代码,这里仍然用4.3的源码看一下,模拟一个场景,APP只有一个Activity,我们主动finish掉这个Activity,APP就回到了后台,这里要记住,虽然没有可用的Activity,但是APP本身是没哟死掉的,这就是所谓的热启动,先看下大体的流程:
以上面描述的push Activity为例,来查看AMS源码:
一开始的流程跟startActivity类似,首先是先暂停当前resume的Activity。相关代码如下:
pause掉当前Activity之后,还需要唤醒上一个Activity,如果当前APP的Activity栈里应经空了,就回退到上一个应用或者桌面程序。对于返回到桌面的情况这里不做深究。其实源码有一段代码是判断,当前的ActivityStack上面是否还有其他的Activity的代码。当Activity回退到后台状态后,系统做了什么事情呢?来看下面的代码:
看一下上面的两个关键点1跟2,1是同startActivity的completePauseLocked不同的地方,主动finish的prev.finishing是为true的,因此会执行finishCurrentActivityLocked分支,将当前pause的Activity加到mStoppingActivities队列中去,并且唤醒下一个需要走到到前台的Activity,唤醒后,会继续执行stop:
再回到resumeTopActivityLocked继续看,resume之后会回调completeResumeLocked函数,继续执行stop,这个函数通过向Handler发送IDLE_TIMEOUT_MSG消息来回调activityIdleInternal函数,最终执行destroyActivityLocked销毁ActivityRecord。
在销毁Activity的时候,如果当前APP的Activity堆栈为空了,就说明当前Activity没有可见界面了,这个时候就需要动态更新这个APP的优先级,详细代码如下:
最终会调用AMS的updateOomAdjLocked函数去更新进程优先级,在4.3的源码里面,主要是通过Process类的setOomAdj函数来设置优先。ActivityManagerService更新优先级的代码在updateOomAdjLocked里面。
最后调用android_util_Process.cpp,通过proc文件系统修改内核信息来动态更新进程的优先级oomAdj,以上是针对Android4.3系统的分析。
Android 5.0的进程优先级更新-LMKD服务
Android5.0将设置进程优先级的入口封装成了一个独立的服务lmkd服务,AMS不再直接访问proc文件系统,而是通过lmkd服务来进行设置,从init.rc文件中看到服务的配置。相关配置如下:
从配置中可以看出,该服务是通过socket与其他进行进程进行通信,其实就是AMS通过socket向lmkd服务发送请求,让lmkd去更新进程的优先级,lmkd收到请求后,会通过/proc文件系统去更新内核中的进程优先级。首先看一下5.0中这一块AMS有什么改变。
本文为授权转载文章,任何人未经原授权方同意,不得复制、转载、摘编等任何方式进行使用,e-works不承担由此而产生的任何法律责任! 如有异议请及时告之,以便进行及时处理。联系方式:editor@e-works.net.cn tel:027-87592219/20/21。