当前位置: 首页 > news >正文

Android 系统的进程模型

Android 的进程模型是其系统架构的核心设计之一,它基于 Linux 进程模型,但结合了 Android 组件化特性和内存管理需求,形成了一套“动态生命周期”和“优先级驱动”的进程管理机制。对于系统开发工程师,需要从以下几个维度理解其设计本质:

1. 基础:基于 Linux 进程,但受 AMS 管控

Android 应用进程本质是 Linux 进程(由 Zygote 进程 fork 生成,共享虚拟机和框架代码),拥有独立的 PID、UID(应用签名决定,用于权限隔离),但进程的创建、存活、销毁并非完全由应用自主控制,而是由 ActivityManagerService(AMS) 主导调度:

  • 进程首次启动时,AMS 通过 Zygote 进程 fork 新进程(避免重复初始化虚拟机,提升启动速度)。
  • 进程的生命周期与组件状态强绑定(如 Activity 前台/后台状态会影响进程优先级)。
  • 系统内存不足时,AMS 会按优先级主动终止低优先级进程,释放资源。

2. 核心:进程优先级(OOM 调整值)

Android 进程的存活优先级由 OOM 调整值(oom_adj) 决定,该值由 AMS 动态计算并通过 Process.setOomAdj() 作用于内核,oom_adj 越小,优先级越高(越难被杀死)。主要优先级从高到低分为以下几类(以 Android 12+ 为例):

优先级类别典型场景oom_adj 范围(示例)说明
前台进程正在交互的 Activity(onResume() 状态)、绑定到前台 Activity 的 Service-1000 ~ -200优先级最高,只有在系统内存极度不足时才可能被杀死(几乎不杀)。
可见进程处于 onPause() 状态的 Activity(如被对话框遮挡)、提供可见 UI 的 Service-199 ~ -100可见但非交互,优先级仅次于前台进程,一般不被杀死。
服务进程已启动的后台 Service(startService())且未绑定前台组件50 ~ 100优先级高于后台进程,系统会尽量保留(如音乐播放 Service)。
后台进程所有 Activity 都处于 onStop() 状态(用户看不到,但未销毁)100 ~ 200优先级较低,内存不足时可能被批量回收,回收后用户返回需重新创建 Activity。
空进程无任何活跃组件(所有组件已销毁,但进程未退出)200+仅作为缓存(加速下次启动),内存不足时优先被杀死。

动态调整逻辑
AMS 通过 ProcessList 实时计算 oom_adj,例如:

  • 当用户切换应用时,前台进程变为后台进程,oom_adj 升高。
  • 后台 Service 调用 startForeground() 可提升为前台服务进程,oom_adj 降低。
  • 进程持有 SYSTEM_ALERT_WINDOW 权限显示悬浮窗时,可能被归类为可见进程。

3. 进程与组件的绑定关系

进程的优先级由其内部最活跃的组件决定(“取最高优先级”原则):

  • 一个进程中若同时有前台 Activity 和后台 Service,进程优先级按前台 Activity 计算。
  • 若进程中只有已停止的 Activity 和一个后台 Service,优先级按 Service 计算(高于纯后台进程)。
  • 当所有组件都销毁后,进程变为空进程,等待被回收或下次复用。

4. 进程间通信(IPC)与隔离

  • 隔离性:不同 UID 的进程默认无法直接访问彼此的内存(Linux 权限机制),需通过 Binder 机制进行 IPC。
  • 共享进程:同一 UID 的应用(如通过 sharedUserId 配置)可运行在同一进程(需指定相同 process 名),共享内存空间。
  • 系统进程system_server 进程(运行 AMS、WMS 等核心服务)、zygote 进程、lmkd(低内存杀手)等系统进程拥有高权限(UID=0 或系统 UID),不受普通应用进程的 OOM 规则限制。

5. 低内存回收机制(LMK)

当系统内存不足时,低内存杀手(Low Memory Killer,LMKD) 会根据 AMS 维护的 oom_adj 列表,按“从低优先级到高优先级”的顺序终止进程:

  • AMS 通过 ProcessList 向内核注册内存阈值(如 criticallow 等),当内存低于阈值时触发回收。
  • 回收策略:优先杀空进程 → 后台进程 → 服务进程(非重要),尽量保留可见和前台进程。
  • 进程被杀死后,其内部组件状态会被 AMS 保存(如 Activity 的 onSaveInstanceState),用户下次访问时重新创建进程并恢复状态。

6. 特殊进程类型

  • Persistent 进程:系统核心进程(如 phone 进程、systemui 进程)在 AndroidManifest.xml 中声明 persistent="true"oom_adj 极低(接近前台进程),除非系统崩溃否则不会被杀死,重启后会自动恢复。
  • 缓存进程:即后台进程和空进程的统称,AMS 会维护一个 LRU(最近最少使用)列表,回收时优先杀死最久未使用的缓存进程。

总结

Android 进程模型的核心是“优先级驱动的动态生命周期管理”:通过 AMS 实时调整进程优先级,结合 LMKD 实现内存的高效利用,同时保证用户可见和交互的进程优先存活。这种设计既满足了多应用并发的需求,又在有限的移动设备内存中平衡了性能与用户体验。对于系统开发,理解 oom_adj 计算逻辑、进程与组件的绑定关系,以及 LMK 的触发机制,是优化系统流畅度和内存占用的关键。

为什么 AMS 通过 Zygote 进程 fork 新进程可以避免重复初始化虚拟机,提升启动速度?

AMS 通过 Zygote 进程 fork 新应用进程能避免重复初始化虚拟机并提升启动速度,核心原因在于 Zygote 进程的“预初始化”和 Linux fork 机制的“写时复制(Copy-On-Write)”特性,二者结合实现了资源复用和启动加速。具体可从以下几个层面理解:

1. Zygote 进程的“预加载”机制

Zygote 是 Android 系统启动时最早创建的用户进程之一(由 init 进程启动),其核心职责是提前初始化应用运行所需的共性资源,避免每个应用进程重复执行这些耗时操作:

  • 虚拟机(ART/Dalvik)初始化:Zygote 进程启动时会先初始化 ART 虚拟机(加载虚拟机核心库、设置运行时环境、初始化垃圾回收机制等),这一过程涉及大量底层库加载和内存分配,耗时较长。
  • 框架资源预加载:Zygote 会提前加载 Android 框架层的核心类(如 ActivityServiceIntent 等,通过 preloadClasses 列表)、系统资源(如 resources.arsc、主题、drawable 等,通过 preloadResources)以及共享库(如 libandroid_runtime.so)。
  • 系统服务连接:Zygote 会提前与 system_server 进程建立通信(如注册到 AMS),为后续 fork 子进程后的组件启动铺路。

这些预加载操作在 Zygote 进程启动时一次性完成,之后所有应用进程通过 fork Zygote 诞生,天然继承这些已初始化的资源,无需重复执行。

2. Linux fork 的“写时复制(Copy-On-Write)”特性

Linux 的 fork 系统调用创建子进程时,并非立即复制父进程的全部内存(否则会导致内存浪费和耗时),而是采用 “写时复制(COW)” 策略:

  • 初始阶段:子进程与父进程共享同一块物理内存(包括 Zygote 预加载的虚拟机、框架类、资源等),仅复制页表(虚拟内存到物理内存的映射关系),这一步几乎瞬时完成。
  • 修改时复制:当子进程需要修改某块内存(如应用自己的代码、数据)时,系统才会为子进程复制该内存页的物理副本,父进程的内存保持不变。

对应用进程而言,Zygote 预加载的大部分资源(如框架类、虚拟机代码)是只读的(应用不会修改),因此子进程可以长期共享这些内存,无需复制。这既节省了内存,又避免了重复加载的时间开销。

3. 对比“独立启动”的劣势

若不通过 Zygote fork,而是让每个应用进程独立启动,会存在两大问题:

  • 重复初始化成本:每个应用都要单独启动虚拟机、加载框架类和资源,这些操作占应用启动时间的 30%~50%(尤其是虚拟机初始化),导致启动缓慢。
  • 内存浪费:每个进程都独立持有一份框架资源副本,而这些资源在所有应用中是通用的,会导致内存占用激增(例如,仅框架类就可能占用数十 MB 内存,多应用叠加后浪费严重)。

4. Zygote 与 AMS 的协同流程

当 AMS 需要启动新应用进程时(如首次启动 Activity 且目标进程不存在),流程如下:

  1. AMS 通过 Process.start() 向 Zygote 发送请求(携带应用包名、UID、进程名等参数)。
  2. Zygote 接收到请求后,调用 fork() 创建子进程(应用进程),子进程继承 Zygote 的虚拟机、预加载资源。
  3. 子进程启动后,通过 ActivityThread.main() 初始化自身(绑定 AMS、创建应用上下文等),但无需重复初始化虚拟机和框架资源。
  4. 子进程通过 IPC 向 AMS 报告“已就绪”,AMS 随后调度组件(如 Activity)启动。

整个过程中,fork 操作因 COW 特性几乎无延迟,子进程直接复用 Zygote 的预加载资源,大幅缩短了启动时间。

总结

Zygote 本质是一个“资源预加载容器”,而 Linux fork 的 COW 机制则是“高效复用资源的载体”。AMS 通过 Zygote fork 新进程,本质上是借助二者的协同,将应用启动的“共性初始化成本”从“每个进程重复执行”优化为“Zygote 一次性执行,所有子进程共享”,从而从根源上避免了重复劳动,实现了启动速度的提升。这一设计是 Android 针对移动设备“内存有限、启动速度敏感”特点的关键优化。

http://www.dtcms.com/a/511502.html

相关文章:

  • vue2实现pdf预览兼容低版本浏览器
  • Android Compose 状态的概念
  • spark组件-spark core(批处理)-rdd持久化机制
  • 安全驾驶 智在掌控|腾视科技ES06终端,为车辆运营赋能
  • el-table 表格嵌套表格
  • 云南网站建设首选才力东营注册公司
  • 非对称密码算法分析技术深度剖析及未来展望
  • Arduino IDE下载安装汉化教程(附安装包,图文并茂)
  • 本地转移新分支到新仓库
  • GaussDB慢sql信息收集和执行计划查看
  • AWS IoT Core 监控与告警优化实战报告
  • 我的第一个开源项目【IOT-Tree Server】
  • 如何选择合适的倾角传感器厂家的产品以满足物联网监测需求?
  • 基于物联网与云计算的园区能耗管理平台构建与实践
  • Markdown 用法要点
  • 网站搭建功能需求wordpress安装怎么填
  • 网络原理:TCP协议
  • timm教程翻译:(六)Data
  • VSCode + AI Agent实现直接编译调试:告别Visual Studio的原理与实践
  • 【设计模式】建造者模式(Builder)
  • DeepSeek-OCR:把长文本“挤进图片”的新思路
  • 计算机做网站开题报告网页的六个基本元素
  • AI服务器工作之整机部件(CPU+内存)
  • 【EE初阶 - 网络原理】网络层 + 数据链路层 + DNS
  • 关于二级网站建设西安网站制作一般多少钱
  • 【机器学习06】神经网络的实现、训练与向量化
  • [人工智能-大模型-25]:大模型应用层技术栈 - 大模型应用层的四大开发模式(如何利用大语言模型?)
  • YOLO目标检测:一种用于无人机的新型轻量级目标检测网络
  • 第六部分:VTK进阶(第166章 标量-向量-张量场管理)
  • A Survey of Camouflaged Object Detection and Beyond论文阅读笔记