NoActive V1 冻结与 Kill 信号方式详解及优缺点
V1 冻结方式
什么是 Cgroup Freezer V1
Cgroup Freezer V1 是 Linux 早期的 cgroup v1 方案中的冻结控制器。相比 V2,V1 存在一些设计局限。
NoActive 的 V1 实现
NoActive 自行实现并封装了 Cgroup Freezer V1 的调用逻辑,通过内核模块桥接到内核接口。
V1 的核心问题
子进程未冻结
V1 模式下,冻结父进程不会自动冻结其子进程。这意味着:
- 应用主进程被冻结了,但 Service 子进程仍在运行
- 未冻结的子进程可能继续消耗 CPU 和内存
- 子进程可能与已冻结的父进程进行 Binder 通信,导致异常
内存泄露风险
早期 V1 实现存在内存泄露问题。新版本增加了防泄露补丁,降低泄露风险,但无法完全消除。
V1 的适用场景
V1 主要适用于 4.19 内核的厂商定制 ROM(MIUI/HyperOS/RealmeUI/ColorOS)。这些 ROM 在内核层面做了大量定制,Cgroup Freezer V2 可能不生效,但 V1 仍可工作。
Kill 冻结方式
Kill 信号暂停机制
Linux 提供了两个与进程暂停相关的信号:
| 信号 | 数值 | 效果 |
|---|---|---|
| SIGSTOP | 19 | 强制停止,不可捕获 |
| SIGTSTP | 20 | 终端停止,可被应用捕获 |
NoActive 通过 Android 的 Process.sendSignal() 封装间接调用 Kill 信号。
Kill 的优点
- 兼容性最好:任何内核都支持,无 Cgroup 依赖
- 无需内核模块:理论上 Kill 方式可以不依赖内核模块(但仍建议刷入以保证完整功能)
Kill 的缺点
内存全解冻
系统内存达到一定阈值时,Kernel 的 Low Memory Killer (LMK) 会杀死进程。Kill 方式下,应用被暂停后,内核可能判定其为"可回收"状态,触发全解冻。
子进程问题
Kill 方式同样存在子进程未冻结的问题。
信号有效性不确定
部分系统对 SIGSTOP (19) 和 SIGTSTP (20) 的处理可能不同,需要自测哪个有效。
Binder 通知问题
冻结后的进程可能仍能接收 Binder 通知,导致文件操作卡屏。建议刷入 ReKernel 或开启文件作用域来缓解。
Kill 的权限问题
在某些严格限制的系统上,直接发送 Kill -19 可能被 SELinux 或安全策略拦截。此时可以尝试以下命令绕过:
su
magiskpolicy --live "allow system_server * process {sigstop}"
V1 vs Kill 选型
| 对比 | V1 | Kill |
|---|---|---|
| 进程覆盖 | 父进程冻结,子进程未冻结 | 同 V1 |
| 内存泄露 | 可能有(V3.2+ 有补丁) | 无 |
| 内核依赖 | 需要内核模块 | 可无 |
| 全解冻风险 | 低 | 高(内存不足时) |
| 兼容性 | 4.19 厂商定制 | 所有内核 |
| 推荐度 | ⭐⭐ | ⭐ |
终极推荐
5.10+ 内核
→ V2
4.19 + 厂商定制(MIUI/HyperOS/RealmeUI/ColorOS)
→ V1
4.19 及以下 + 非厂商定制
→ Kill
以上都不生效
→ 排查内核模块是否正常
→ 尝试 magiskpolicy 绕过权限限制
→ 继续 内核版本与冻结方式对应关系