android 进程保活

转载自:
https://blog.csdn.net/xiaoxiaohu_/article/details/73639637
http://www.infoq.com/cn/articles/wechat-android-background-keep-alive
https://www.jianshu.com/p/63aafe3c12af
在安卓系统中,进程被杀的原因通常分为几个方面:
1、应用crash
2、系统回收内存
3、用户触发
4、第三方root权限app

这里讨论的是第2项,如何应对android Lowmemory killer。

熟悉安卓系统的人都知道,系统处于体验和性能的考虑,app在退到后台时系统并不会真正的kill掉这个进程,而是将这个进程缓存起来,打开的应用越多,后台缓存的进程也就越多,在系统内存不足的情况下,系统开始依据自身的一套进程回收机制来判断要kill掉哪些进程,以腾出内存来供给需要的app。这套回收内存的机制叫做Low memory killer。他是基于Linux内核OOM killer(out of memory killer)机制诞生。

了解完Low Memory killer,再说一下oom_adj。他是linux内核分配给每个系统进程的一个值,代表进程的优先级,进程回收机制就是根据这个优先级来决定是否进行回收。oom_adj的作用有以下几点:

  • 进程的oom_adj越大,表示此进程的优先级越低,越容易被杀回收;越小,表示进程优先级越高,越不容易被杀回收
  • 普通app进程的oom_adj>=0,系统进程的oom_adj才可能小于0.

可以用到下面两个命令来查看进程的oom_adj值,

ps | grep PackageName //获取制定进程的信息

这里写图片描述
红色圈中是下面三个进程的id
UI进程:com.clock.daemon
普通后台进程:com.clock.daemon:bg
灰色保活进程:com.clock.daemon:gray
这些也可以在android studio中获得:
这里写图片描述

接下来获取三个进程的oom_adj

cat /proc/进程ID/oom_adj

这里写图片描述
从上图可以看出,UI进程和灰色保活service进程的oom_adj=0,而普通后台进程oom_adj =15 到这里你估计也能明白,为什么普通的后台进程容易被回收,而前台进程不容易被回收。
看看下面的图:
这里写图片描述
我把app切换到后台,再进行oom_adj的实验,你会发现UI进程的值从0变成6,灰色保活的service进程从0变成1,这里可以观察到,app退到后台时,其所有的进程优先级都会降低,但是UI进程是降低非常明显的,因为他占用资源最多,系统内存不足的时候肯定优先杀这些占用内存高的进程来腾出资源,所以,为了尽量避免后台UI进程被杀,需要极可能的释放一写不用的资源,尤其是图片,音频之类的。

下面分享几种微信保活的方法:

进程拆分

很多人在实际开发中,基本都不会去给app划分进程,而且,在android中使用多进程,还可能需要编写额外的进程通信代码,可能带来额外的bug,无疑加大了开放的工作量。

整个app在一个进程有什么弊端

在android中,虚拟机飞赔给各个进程的运行内存是有限制的(可能是32M,48M,64M,根据机型而定)如果在app中,增加了一个很常用的图片选择模块用于上传图片或者头像,加载大量bigmap会使app的内存占用迅速增加,如果你还把查看过的图片缓存在了内存中,那么OOM的风险将会大大增加,如果此时还需要使用Webview加载一波网页,那这就很危险了。
微信开发团队在《android内存优化杂谈》一文中就说到:“对于Webview,图库等,由于存在内存系统泄露或者占用内存过多的问题,我们可以采用单独的进程,微信当前也会把它们放在单独的tool进程中。”
这里写图片描述
上图表示的是微信主要的几个进程:
1、push主要用于网络交互,没有UI
2、worker就是用户看到的主要UI
3、tools主要包含gallery和webview
拆分网络进程,确实是为了减少进程回收带来的网络断开
这里写图片描述
可以看到push的内存要远远小于worker,而且push的工作性质稳定,内存增长非常少,这样就可以保证,尽量减少push被杀的可能性。
这里有个思路,但是限制比较多,启动一个纯c/c++进程,没有java run time,内存使用极低。
这种做法限制很明显,如没有java run time,所以无法使用android系统接口,缺乏权限,也无法使用分钟shell命令操作(如am)但可以考虑一下用途:高强度运算,网络连接,心跳维持等。比如shadowsocks-android就如此,使用纯c命令行进程,维护和socks5的代理

tools进程的拆分同样也是内存原因:
1、老版本的webview是有内存泄露的
2、Gallery大量缩略图导致内存使用大
微信在进入后台后,会主动把tools进程kill掉。

及时拉起

系统回收不可避免,即使重新拉起的手段主要依赖系统特性,从上图可以看到,push有AlarmReceiver ConnectReceiver BootReceiver。这些receiver都可以在push被杀后,重新拉起。特别AlarmReceiver,结合心跳逻辑,微信被杀后,重新拉起最多一个心跳周期。
而对于worker,除了用户UI操作启动。在接收消息,或者网络切换等事件,push也会通过LocalBroadcast,重新拉起worker。这种拉起worker,大部分初始化已经完成,也能大大提高用户点击微信的启动速度。

进程优先级

Low Memory Killer决定是否杀进程除了内存的大小,还有进程优先级。提高进程优先级是保活的最好手段
原理:android的前台service机制。但该机制的缺陷是通知栏保留了图标。
对于 API level<18,调用startForeGround(ID,new Norification())发送空的Notification,图标则不会显示。
对于API level >=18,在需要提高优先级的service A启动一个InnerService,两个服务同时startForeground,且绑定同样的ID。stop掉InnerService,这样通知栏的图标即被移除。
这种方案其实是利用的android 前台service的漏洞。

猜你喜欢

转载自blog.csdn.net/u011337574/article/details/80042706