当前位置:网站首页>im即时通讯开发:进程被杀底层原理、APP应对被杀技巧
im即时通讯开发:进程被杀底层原理、APP应对被杀技巧
2022-06-10 12:59:00 【wecloud1314】
本文的技术原理讲解透彻、系统源码分享到位、样例代码也很有参考意义,希望能对有同样兴趣爱好的Android开发者、IM开发者、推送系统开发者等,带来对于Android进程保活技术的深入理解。
一直以来,App 进程保活都是各大厂商,特别是头部应用开发商永恒的追求。毕竟App 进程死了,就什么也干不了了。一旦 App 进程死亡,那就再也无法在用户的手机上开展任何业务,所有的商业模型在用户侧都没有立足之地了。

早期的 Android 系统不完善,导致 App 侧有很多空子可以钻,因此它们有着有着各种各样的姿势进行保活。
譬如说在 Android 5.0 以前,App 内部通过 native 方式 fork 出来的进程是不受系统管控的,系统在杀 App 进程的时候,只会去杀 App 启动的 Java 进程。因此诞生了一大批“毒瘤”,他们通过 fork native 进程,在 App 的 Java 进程被杀死的时候通过 am命令拉起自己从而实现永生。
那时候的 Android 可谓是魑魅横行,群魔乱舞,系统根本管不住应用,因此长期以来被人诟病耗电、卡顿。
同时,系统的软弱导致了 Xposed 框架、阻止运行、绿色守护、黑域、冰箱等一系列管制系统后台进程的框架和 App 出现。
不过,随着 Android 系统的发展,这一切都在往好的方向演变。
Android 5.0 以上,系统杀进程以 uid 为标识,通过杀死整个进程组来杀进程,因此 native 进程也躲不过系统的法眼。
Android 6.0 引入了待机模式(doze),一旦用户拔下设备的电源插头,并在屏幕关闭后的一段时间内使其保持不活动状态,设备会进入低电耗模式,在该模式下设备会尝试让系统保持休眠状态。
Android 7.0 加强了之前鸡肋的待机模式(不再要求设备静止状态),同时对开启了 Project Svelte。Project Svelte 是专门用来优化 Android 系统后台的项目,在 Android 7.0 上直接移除了一些隐式广播,App 无法再通过监听这些广播拉起自己。
Android 8.0 进一步加强了应用后台执行限制:一旦应用进入已缓存状态时,如果没有活动的组件,系统将解除应用具有的所有唤醒锁。另外,系统会限制未在前台运行的应用的某些行为,比如说应用的后台服务的访问受到限制,也无法使用 Mainifest 注册大部分隐式广播。
Android 9.0 进一步改进了省电模式的功能并加入了应用待机分组,长时间不用的 App 会被打入冷宫。另外,系统监测到应用消耗过多资源时,系统会通知并询问用户是否需要限制该应用的后台活动。
然而,道高一尺,魔高一丈。系统在不断演进,保活方法也在不断发展。
大约在 4 年前出现过一个 MarsDaemon,这个库通过双进程守护的方式实现保活,一时间风头无两。不过好景不长,进入 Android 8.0 时代之后,这个库就逐渐消亡。

一般来说,Android 进程保活分为两个方面:
1)保持进程不被系统杀死;
2)进程被系统杀死之后,可以重新复活。
随着 Android 系统变得越来越完善,单单通过自己拉活自己逐渐变得不可能了。
因此,后面的所谓「保活」基本上是两条路:
1)提升自己进程的优先级,让系统不要轻易弄死自己;
2)App 之间互相结盟,一个兄弟死了其他兄弟把它拉起来。
当然,还有一种终极方法,那就是跟各大系统厂商建立 PY 关系,把自己加入系统内存清理的白名单——比如说国民应用微信。当然这条路一般人是没有资格走的。
知己知彼,百战不殆。既然我们想要保活,那么首先得知道我们是怎么死的。
一般来说,系统杀进程有两种方法,这两个方法都通过 ActivityManagerService 提供:
1)killBackgroundProcesses;
2)forceStopPackage。
在原生系统上,很多时候杀进程是通过第一种方式,除非用户主动在 App 的设置界面点击「强制停止」。
不过国内各厂商以及一加三星等 ROM 现在一般使用第二种方法。因为第一种方法太过温柔,根本治不住想要搞事情的应用。第二种方法就比较强力了,一般来说被 force-stop 之后,App 就只能乖乖等死了。
因此,要实现保活,我们就得知道 force-stop 到底是如何运作的。
既然如此,我们就跟踪一下系统的 forceStopPackage 这个方法的执行流程。
那么,如何实现逃脱被杀呢?我们看这个关键的 5ms。
假设:App 进程在被杀掉之后,能够以足够快的速度(5ms 内)启动一堆新的进程,那么系统在一次循环杀掉老的所有进程之后,sleep 5ms 之后又会遇到一堆新的进程。
如此循环 40 次,只要我们每次都能够拉起新的进程,那我们的 App 就能逃过系统的追杀,实现永生。
是的:炼狱般的 200ms,只要我们熬过 200ms 就能渡劫成功,得道飞升。不知道大家有没有玩过打地鼠这个游戏,整个过程非常类似,按下去一个又冒出一个,只要每次都能足够快地冒出来,我们就赢了。即时通讯开发
现在问题的关键就在于:如何在 5ms 内启动一堆新的进程?
再回过头来看原来的保活方式:它们拉起进程最开始通过am命令,这个命令实际上是一个 java 程序,它会经历启动一个进程然后启动一个 ART 虚拟机,接着获取 ams 的 binder 代理,然后与 ams 进行 binder 同步通信。这个过程实在是太慢了,在这与死神赛跑的 5ms 里,它的速度的确是不敢恭维。
后来:MarsDaemon 提出了一种新的方式,它用 binder 引用直接给 ams 发送 Parcel,这个过程相比 am命令快了很多,从而大大提高了成功率。
其实这里还有改进的空间,毕竟这里还是在 Java 层调用,Java 语言在这种实时性要求极高的场合有一个非常令人诟病的特性:垃圾回收(GC)。
虽然我们在这 5ms 内直接碰上 gc 引发停顿的可能性非常小,但是由于 GC 的存在,ART 中的 Java 代码存在非常多的 checkpoint。想象一下你现在是一个信使有重要军情要报告,但是在路上却碰到很多关隘,而且很可能被勒令暂时停止一下,这种情况是不可接受的。
因此,最好的方法是通过 native code 给 ams 发送 binder 调用。当然,如果再底层一点,我们甚至可以通过 ioctl 直接给 binder 驱动发送数据进而完成调用,但是这种方法的兼容性比较差,没有用 native 方式省心。
通过在 native 层给 ams 发送 binder 消息拉起进程,我们算是解决了「快速拉起进程」这个问题。但是这个还是不够。
还是回到打地鼠这个游戏,假设你摁下一个地鼠,会冒起一个新的地鼠,那么你每次都能摁下去最后获取胜利的概率还是比较高的;但如果你每次摁下一个地鼠,其他所有地鼠都能冒出来呢?这个难度系数可是要高多了。如果我们的进程能够在任意一个进程死亡之后,都能让把其他所有进程全部拉起,这样系统就很难杀死我们了。
新的黑科技保活中通过 2 个机制来保证进程之间的互相拉起:
1)2 个进程通过互相监听文件锁的方式,来感知彼此的死亡;
2)通过 fork 产生子进程,fork 的进程同属一个进程组,一个被杀之后会触发另外一个进程被杀,从而被文件锁感知。
具体来说:
1)创建 2 个进程 p1、p2,这两个进程通过文件锁互相关联,一个被杀之后拉起另外一个;
2)同时 p1 经过 2 次 fork 产生孤儿进程 c1,p2 经过 2 次 fork 产生孤儿进程 c2,c1 和 c2 之间建立文件锁关联。
这样假设 p1 被杀,那么 p2 会立马感知到,然后 p1 和 c1 同属一个进程组,p1 被杀会触发 c1 被杀,c1 死后 c2 立马感受到从而拉起 p1,因此这四个进程三三之间形成了铁三角,从而保证了存活率。
分析到这里,这种方案的大致原理我们已经清晰了。基于以上原理,我写了一个简单的验证性代码(代码在下方)有兴趣的可以看一下。
边栏推荐
- 【深度学习】基于深度学习Autoencoder的信用卡欺诈异常检测,效果非常牛逼
- Apple邮箱配置QQ邮箱,163邮箱,edu邮箱,gmail邮箱,获取gmail日历
- Site investigation system
- Binary XML file line 96: error inflating class & lt; unknown>
- 移动app性能测试有哪些需要进行?性能测试报告如何收费?
- Which EDA design software should Altium Allegro pads choose
- Asynchronous export of Excel
- 如果再写for循环,我就锤自己了
- Development trend of Web Development
- 世贸组织MC12重启 议程重点关注全球经济复苏
猜你喜欢

Commencez par interpréter le Code généré automatiquement par la BDC et expliquez les composantes du programme de l'interface graphique SAP.

Don't mistake "it informatization" for "super project"

Code free may event Microsoft low code matrix update; Multiple industry reports released

QT database application 22 file coding format recognition

32. Simple test of raspberry pie serial port communication and ultrasonic module ranging

WT2003H4-16S 语音芯片按键录音及播放应用解析

13、 System call and shell (freesanding shell, terminal and job control)

JS click the button to slide to the left
![[deep learning] the credit card fraud anomaly detection based on the deep learning autoencoder is very effective](/img/69/505707755e6b003d90cdb07e61914a.jpg)
[deep learning] the credit card fraud anomaly detection based on the deep learning autoencoder is very effective

Introduction to assembly language - Summary
随机推荐
The deep neural network classifies nearly 2billion images per second, and the new brain like optical classifier chip is on nature
线性动态规划专讲
Student status management system
Ekuiper newsletter 2022-05 protobuf codec support, visual drag and drop writing rules
"Reduce the burden" so that the "pig" can fly higher
10、 Application of state machine model (cellular automata; gdb/rr/perf; code verification tool)
讓資源在雲端和本地自由流動
Cvpr2022|aconvnetforthe2020s & how to design neural network Summary
Neuron newsletter 2022-05 | add 2 southbound drivers and 1 northbound application, and realize customized extension with Modbus TCP
Recommended learning materials for Altium Designer
How to write code that is not easy to overflow memory
12、 Process address space (PMAP; vdso; MMAP)
If I write the for loop again, I will hammer myself
Use and inspection of safety tools and instruments
If the files and graphics are lost, it means that you don't need the office developed by yourself
[raise bar C #] how to call the base of the interface
The essence of linear algebra 6 inverse matrix, column space and zero space
3. web page development tool vs Code
小笔记-简单但够用系列_yapi 返回参数 data 应当是 object 类型问题解决记录
Office technical lecture: punctuation - Chinese - vertical