这两天火星了一件事, Android 不喜欢 fork()/exec() - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
acess
V2EX    Android

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

  •  2
     
  •   acess 2024-06-10 18:14:05 +08:00 via Android 9689 次点击
    这是一个创建于 512 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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
       2024-06-10 18:18:37 +08:00 via Android
    这件事其实还让我想起来很多年前 @madeye 接受的一个 PR ,在 shadowsocks-android 里引入了进程被杀自动重启的 GuardedProcessPool 机制:

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

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

    现在看其实 ss-android 一直以来都在用幽灵进程支持自己的核心功能……(天
    acess
        2
    acess  
    OP
       2024-06-10 18:26:15 +08:00 via Android
    (啊啦坏了,一处 W^X 我写错成 R^X 了,捂脸)
    codehz
        3
    codehz  
       2024-06-10 19:45:56 +08:00
    还记得之前有个保活技巧就是开一大堆进程互相检测,只要进程生成的比杀的快,(要非常多,不然跑不过),就可以躲过“强制停止”按钮和自动终止后台执行的机制,因为先前版本的强制停止只是循环杀进程 5 秒,之后就放过了
    benhaz
        4
    benhaz  
       2024-06-10 20:03:53 +08:00
    @codehz 估计这电量也消耗的巨快(捂脸
    acess
        5
    acess  
    OP
       2024-06-10 21:42:26 +08:00 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  
       2024-06-10 23:20:25 +08:00   1
    native 实在是黑科技太多了,pdd 已经玩的出神入化
    tool2dx
        7
    tool2dx  
       2024-06-11 00:58:39 +08:00
    我这里 adb+root 出来的 exec 进程,可以 24 小时运行,并不会被杀掉。

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

    这情况 termux 做不到。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5826 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 01:48 PVG 09:48 LAX 17:48 JFK 20:48
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86