Android 从一开始就不喜欢 Linux native executables ,认为这玩意游离于 Android framework 管理之外,属于灰色地带,不被鼓励,甚至默认这类进程随时可以被系统杀掉。
这件事最让我感觉难受的是,Google 是太懒了么?好像从一开始,甚至一直到今天,都仍然没有在官方文档里写明这件事。
早在 2013 年,stackoverflow 上就有相关问答,虽然很显然这并不是官方口径:
https://stackoverflow.com/questions/16179062/using-exec-with-ndk
呃虽然不是 Google 官方下场答的,但这个答主的理解被 Google 官方认可了。在 Android 10 执行 R^X 安全政策,禁止从可写的应用数据目录执行原生代码时(但打包在 APK 内并声明会解压到只读位置则仍然允许执行),Google 方面就在解释时引用了上面这个回答:
https://issuetracker.google.com/issues/128554619#comment4
然后 Android 12 时代 Google 同样是在未文档的情况下引入了一个“幽灵进程杀手”机制,连带 W^X 在一起简直是想要 Termux 死……于是 Termux 开发者替 Google 整理了一份文档:
而且他还跑去 AOSP 官方 issue tracker 据理力争了一把……
值得庆幸的是 Google 还是听进去了一点,在 Android 14 引入了一个开发者选项,可以彻底把幽灵进程杀手关掉:
1
acess OP 这件事其实还让我想起来很多年前 @madeye 接受的一个 PR ,在 shadowsocks-android 里引入了进程被杀自动重启的 GuardedProcessPool 机制:
https://github.com/shadowsocks/shadowsocks-android/pull/594 那个时候好像认为这属于 vendor-specific bug (?明明是故意的) 现在看其实 ss-android 一直以来都在用幽灵进程支持自己的核心功能……(天 |
2
acess OP (啊啦坏了,一处 W^X 我写错成 R^X 了,捂脸)
|
3
codehz 164 天前
还记得之前有个保活技巧就是开一大堆进程互相检测,只要进程生成的比杀的快,(要非常多,不然跑不过),就可以躲过“强制停止”按钮和自动终止后台执行的机制,因为先前版本的强制停止只是循环杀进程 5 秒,之后就放过了
|
5
acess OP @codehz https://weishu.me/2020/01/16/a-keep-alive-method-on-android/
重点貌似不是进程多让系统杀不过来,而是…… 杀一个进程的时候另一个能立即感知(通过文件锁实现); 然后第二个重点是在 5ms 内完成重启。 非常令人意外地,因为系统每执行一轮追杀就要歇息 5ms ,所以另一个进程居然还享有 5ms 时间能够做出反应。只要它在这 5ms 之内能通知 binder 完成重启复活,然后因为系统只重复追杀 40 次(所以也不是“持续杀 5 秒”而是只有 200ms ),40 次追杀都逃过了系统就不再继续追杀了,等于放过。 |
6
seers 164 天前 1
native 实在是黑科技太多了,pdd 已经玩的出神入化
|
7
tool2dx 164 天前
我这里 adb+root 出来的 exec 进程,可以 24 小时运行,并不会被杀掉。
当然你用 ndk 的 exec 肯定不行,哪怕 root 也不行。包括 termux+sudo 也不行。 |
8
kkocdko 164 天前
感谢楼主的整理,之前看过 termux 开发者的抱怨,之后旧手机就停在 android 10 继续用了,没想到事情这么复杂。
|
9
guo4224 163 天前 via iPhone
谷歌提供了新的 syscall 吗?
|
10
zhenjiachen 163 天前
我去知道,我用 rust 开发了安卓的 sdk ,刚好里面有调用命令行的代码,那这样不会也被杀进程吧?
|
11
acess OP @tool2dx 诶我这边感觉,之前看过 weishu 的博客讲解,现代 root 方案本来就是类似 ssh 到本机那样的“远程 root”,而并不是 app 自己的进程 fork 出来的
@kkocdko 啊呀别感谢了,今天发现很多地方我都疏漏了,比如 Android12 之后,Android12L 其实就已经引入了一个设置参数来完全关闭幽灵进程杀手,只不过是这个参数不在开发者设置 UI 里,只能通过命令行设置,Android14 只是在开发者设置 UI 里新增了设置项(而且和之前的命令行设置不完全一样,命令行设置可以永久保存,开发者设置这边则是如果关闭了开发者设置就会重置)。再比如 Android5 以前其实只要 fork 出去,force-stop 甚至完全不会杀到你,是 Android5 才开始管到 fork 出去的原生进程,等等…… @zhenjiachen termux 开发者提到过,杀的时候看 app 进程的 oom_adj ,还看进程自己什么时候启动的,启动早运行久的优先杀。而且杀进程动作触发也不是非常频繁。所以按我理解的话……如果只是短暂启动执行一个命令马上就退出那被杀几率应该非常小,但也不好说,因为系统默认全局所有 app 加起来只允许 32 个幽灵进程存在,如果别的 app 在搞事,正巧在你执行命令的时候开了一堆幽灵进程出来跟你抢,这个几率也不严格是 0 吧。 |