我们可以把 system_serverAppZygote 之间的关系想象成一个“家族遗传”系统。

一、 三者之间的关系:孵化与监管

  1. Zygote (受精卵进程)
  • 角色:所有 Android Java 进程的“始祖”。
  • 作用:它在开机时启动,预先初始化好 Dalvik/ART 虚拟机,并预加载最常用的 系统类库和资源
  1. system_server (系统服务进程)
  • 产生方式:由 Zygote 在开机阶段 第一个 fork() 出来的子进程。
  • 关系:它是 Zygote 的“长子”。它承载了 Android 绝大多数的核心服务(如 ActivityManagerService, WindowManagerService 等)。
  1. App 进程
  • 产生方式:当你要启动一个 App 时,system_server 会通过 Socket 发送指令给 Zygote,让 Zygote fork() 出一个新的子进程。
  • 关系:App 进程是 Zygote 的“次子”们。
调用链条:
App 启动请求 -> system_server -> Socket 指令 -> Zygote -> fork() -> App 进程

二、 继承的内存地址空间

由于采用了 Linux 的 Copy-on-Write (COW,写时拷贝) 技术,App 进程和 system_server 从 Zygote 那里继承了大量的内存空间。在 fork 的瞬间,物理内存是共享的。
具体继承的内容包括:
1. 预加载的类 (Preloaded Classes)
  • 内容:大约 4000 多个核心 Java 类(如 java.lang.*, android.view.View, android.app.Activity)。
  • 地址空间:这些类被加载后,其方法区、静态变量等元数据在所有 App 进程中地址是一致的。
2. 共享库 (Shared Libraries / .so文件)
  • 内容:底层的 C/C++ 库(如 libc.so, libm.so, libart.so)。
  • 地址空间:通过 mmap 映射到进程的虚拟地址空间。由于 Zygote 已经映射好了,子进程直接继承这些映射关系。
3. 预加载资源 (Preloaded Resources)
  • 内容:系统通用的图标、布局(framework-res.apk 中的资源)。
  • 地址空间:资源索引表和常用的图片缓冲。
4. 虚拟机堆空间 (VM Heap)
  • 内容:Zygote 启动时初始化的 Java 堆环境。
  • 特性:虽然 App 启动后会有自己的堆,但初始状态下,那些只读的系统对象是共享的。

三、 为什么能实现“地址空间继承”?

这得益于 Linux 的虚拟内存管理机制:
  1. 相同的虚拟地址映射
Zygote 在 fork 之前,已经把 framework.jar 等资源映射到了它的虚拟地址空间(例如 0x70000000)。
  1. 物理内存共享
fork 发生时,操作系统只是复制了页表(虚拟地址到物理地址的索引),而没有复制物理内存。
  1. 隔离性
  • 如果 App 只是 读取 这些资源(比如调用 View 类),它就一直和 Zygote 共享同一块物理内存。
  • 一旦 App 尝试 修改 这些内存(比如修改一个全局变量),内核才会为 App 拷贝出一份新的物理内存页。

四、 总结:为什么要这么设计?

  • 省内存:如果 20 个 App 都加载自己的 framework.jar,内存会瞬间耗尽。通过继承,这部分内存只占用一份物理空间。
  • 秒开 App:App 进程不需要重新启动虚拟机,也不需要重新加载几千个类,因为它“继承”了一个已经运行好的环境,只需要执行自己的 main 方法即可。
一句话总结:
system_serverApp 都是 Zygote 镜像的克隆。它们共享了系统最沉重的“基础设施内存”,从而保证了 Android 系统的多任务高效运行。
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐