V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
acess
V2EX  ›  Android

这两天火星了一件事, Android 不喜欢 fork()/exec()

  •  2
     
  •   acess · 8 天前 via Android · 2790 次点击

    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 整理了一份文档:

    https://github.com/agnostic-apollo/Android-Docs/blob/master/en/docs/apps/processes/phantom-cached-and-empty-processes.md

    而且他还跑去 AOSP 官方 issue tracker 据理力争了一把……

    值得庆幸的是 Google 还是听进去了一点,在 Android 14 引入了一个开发者选项,可以彻底把幽灵进程杀手关掉:

    https://issuetracker.google.com/issues/205156966#comment120

    13 条回复    2024-06-11 11:20:44 +08:00
    acess
        1
    acess  
    OP
       8 天前 via Android
    这件事其实还让我想起来很多年前 @madeye 接受的一个 PR ,在 shadowsocks-android 里引入了进程被杀自动重启的 GuardedProcessPool 机制:

    https://github.com/shadowsocks/shadowsocks-android/pull/594

    那个时候好像认为这属于 vendor-specific bug (?明明是故意的)

    现在看其实 ss-android 一直以来都在用幽灵进程支持自己的核心功能……(天
    acess
        2
    acess  
    OP
       8 天前 via Android
    (啊啦坏了,一处 W^X 我写错成 R^X 了,捂脸)
    codehz
        3
    codehz  
       7 天前
    还记得之前有个保活技巧就是开一大堆进程互相检测,只要进程生成的比杀的快,(要非常多,不然跑不过),就可以躲过“强制停止”按钮和自动终止后台执行的机制,因为先前版本的强制停止只是循环杀进程 5 秒,之后就放过了
    benhaz
        4
    benhaz  
       7 天前
    @codehz 估计这电量也消耗的巨快(捂脸
    acess
        5
    acess  
    OP
       7 天前 via Android
    @codehz https://weishu.me/2020/01/16/a-keep-alive-method-on-android/

    重点貌似不是进程多让系统杀不过来,而是……

    杀一个进程的时候另一个能立即感知(通过文件锁实现);

    然后第二个重点是在 5ms 内完成重启。

    非常令人意外地,因为系统每执行一轮追杀就要歇息 5ms ,所以另一个进程居然还享有 5ms 时间能够做出反应。只要它在这 5ms 之内能通知 binder 完成重启复活,然后因为系统只重复追杀 40 次(所以也不是“持续杀 5 秒”而是只有 200ms ),40 次追杀都逃过了系统就不再继续追杀了,等于放过。
    seers
        6
    seers  
       7 天前   ❤️ 1
    native 实在是黑科技太多了,pdd 已经玩的出神入化
    tool2dx
        7
    tool2dx  
       7 天前
    我这里 adb+root 出来的 exec 进程,可以 24 小时运行,并不会被杀掉。

    当然你用 ndk 的 exec 肯定不行,哪怕 root 也不行。包括 termux+sudo 也不行。
    kkocdko
        8
    kkocdko  
       7 天前
    感谢楼主的整理,之前看过 termux 开发者的抱怨,之后旧手机就停在 android 10 继续用了,没想到事情这么复杂。
    guo4224
        9
    guo4224  
       7 天前 via iPhone
    谷歌提供了新的 syscall 吗?
    zhenjiachen
        10
    zhenjiachen  
       7 天前
    我去知道,我用 rust 开发了安卓的 sdk ,刚好里面有调用命令行的代码,那这样不会也被杀进程吧?
    acess
        11
    acess  
    OP
       7 天前 via Android
    @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 吧。
    acess
        12
    acess  
    OP
       7 天前 via Android
    @codehz 说实话经你这么说我昨天也感觉有点不明白了,因为回头看 weishu 的讲解里很强调 5ms ,但好像……这个 5ms 是对[同一个进程组]反复追杀时的歇息间隔,而如果我没理解错,被杀掉的这一组已经没办法做出什么反应了,是监视着它们的,受到文件锁关联的[另一组进程]立即可以感知到兄弟阵亡并马上反应……那么,还没被追杀波及到的[另一组进程]反应时间还是 5ms 吗?想到这里我就感觉有点奇怪,但我也太懒了所以没有继续深究(逃
    tool2dx
        13
    tool2dx  
       7 天前
    @acess 我这里是安卓 12 ,试过很多方法保活都没用。唯一有效的,是父进程 pid 为 0 的情况,系统就会放你一马。

    这情况 termux 做不到。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3130 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 71ms · UTC 11:21 · PVG 19:21 · LAX 04:21 · JFK 07:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.