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

Zygote 进程启动流程

核心目标:理解 Android 系统服务和应用进程的起源

  • 系统服务(SystemServer)的起源:我们手机里的各种系统服务,如活动管理(ActivityManager)、窗口管理(WindowManager)、包管理(PackageManager)等,都不是凭空产生的。它们都运行在一个名为 system_server 的进程中,而这个进程正是由 Zygote 进程“孵化”(fork)出来的
  • 应用进程的起源:当你点击一个 App 图标时,系统需要为这个 App 创建一个新的进程来运行它的代码。为了极致地优化启动速度和内存占用,Android 不会在这个新进程里从头开始加载 Android 框架所需的类和资源,而是直接复制(fork)已经准备好的 Zygote 进程。这样,新进程一诞生就天然继承了 Zygote 已经预加载好的所有资源,从而能够快速启动

Zygote 的核心思想就是 “共享内存,写时复制(Copy-on-Write)”。通过预先加载通用的、只读的代码和资源(如Android框架的类库、主题资源等),让所有子进程共享同一块内存空间。只有当某个进程试图修改这些共享内容时,系统才会为其复制一份副本。这极大地节省了内存和启动时间

学习路径分解

研究 Zygote 启动流程的三个关键步骤,我们逐一进行详细分析

第一步:从 init.rc 脚本开始,追踪 Zygote 的启动参数
  • init.rc 是什么?
    Android 设备启动时,内核加载完成后启动的第一个用户空间进程是 init(初始化进程)。init 进程的责任之一是解析和执行一系列扩展名为 .rc 的初始化脚本文件。init.rc 是其中最核心的主脚本,它定义了在启动特定阶段需要执行的服务(service)和动作(action)
  • Zygote 在 init.rc 中的定义
    在 init.rc(或通常由 init.zygoteXX.rc 导入,如 init.zygote32.rc for 32位)中,你会找到类似这样的服务声明:
    service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server --socket-name=zygoteclass mainsocket zygote stream 660 root system...
    ○ service zygote:定义了一个名为 “zygote” 的系统服务
    ○ /system/bin/app_process:这是 Zygote 进程真正的可执行文件。它是一个通用的 Android 应用进程启动器
    ○ -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote:这些是传递给 app_process 的启动参数
    ◎ 
    --zygote:告诉 app_process:“请以 Zygote 模式运行”
        ◎ --start-system-server:指示 Zygote 在启动后立即“孵化”(fork)并启动 SystemServer 进程。这就是系统服务的起源
        ◎ --socket-name=zygote:指定 Zygote 要监听的 Socket 名称,后续应用进程的启动请求就是通过这个 Socket 通信的
    ○ socket zygote stream 660 root system:同时创建一个名为 “zygote” 的 Unix Domain Socket,并设置其权限。这是 Zygote 与其他进程通信的桥梁

小结: 这一步明确了 Zygote 是由 init 进程根据脚本配置启动的,其二进制文件是 app_process,并获得了关键的执行参数

第二步:分析 app_main.cpp 的 main 函数
  • 这个文件是干什么的?
    app_main.cpp 是 app_process 可执行文件的源码文件。它的 main() 函数是 Zygote 进程的原生(Native,C++)入口点
  • main 函数的关键工作:
    ① 解析参数
    :接收并解析从 init.rc 传过来的参数(如 --zygote--start-system-server
    ② 创建 AppRuntime:实例化一个 AppRuntime 对象(它是 AndroidRuntime 的子类),这是启动 Android Java 世界的核心类
    ③ 准备虚拟机参数:根据启动参数配置 Java 虚拟机(JVM/ART)的各种选项,例如堆大小、垃圾回收策略等(-Xzygote 参数就在这里处理)
    ④ 启动虚拟机并进入 Java 世界:这是最关键的一步。调用 runtime.start(“com.android.internal.os.ZygoteInit”, args, zygote)
        ◎ 这个调用会启动 Android 运行时环境(ART)
        ◎ 然后,它并不是直接运行一个 Java 类的 main 方法,而是通过 JNI 调用 com.android.internal.os.ZygoteInit 类的 main 方法
        ◎ 从此,执行流程就从 C++ 原生代码 跳转到了 Java 代码。Zygote 进程的核心逻辑正式开始

小结: app_main.cpp 是承上启下的枢纽。它作为原生入口,解析配置,初始化 Android 运行时,并将执行权交给 Java 端的 ZygoteInit 类

第三步:理解 ZygoteInit.java 的 main 方法

这是 Zygote 启动流程的 Java 层核心。它的 main 方法主要完成三件大事

  1. 预加载资源(preload)
    static void preload() {preloadClasses(); // 预加载 frameworks.jar 中列出的常用类(在 preloaded-classes 文件中定义),数量高达上千个。preloadResources(); // 预加载系统资源(如 frameworks-res.apk 中的颜色、尺寸、字符串、图片等),这样所有应用进程都能共享这些资源,无需各自加载。preloadSharedLibraries(); // 预加载共享库(如 android, jnigraphics 等)preloadTextResources(); // 预加载文字相关资源// 等等...
    }

    目的:极大提升应用进程的启动速度,并节省内存。这些只读资源在所有子进程间是共享的

  2. 启动 SystemServer(forkSystemServer)
    ○ 
    这是 Zygote 孵化的第一个子进程
    ○ 
    通过 Zygote.forkSystemServer() 方法,当前进程(Zygote)调用 fork() 系统调用,分裂出一个与自己几乎一模一样的子进程(即 system_server
    ○ 在子进程(system_server)中,会脱离 Zygote 的启动路径,转而调用 com.android.server.SystemServer 类的 main 方法,开始启动所有 Java 编写的系统服务
    ○ 从此,Android 系统的核心大脑就开始运转了

  3. 进入 Socket 循环等待创建新应用进程(runSelectLoop)
    ○ 
    在完成上述任务后,Zygote 的使命就变成了“待命”,等待创建新的应用进程
    ○ 它调用 ZygoteServer.runSelectLoop() 方法,在一个死循环中监听之前创建的 “zygote” Socket
    ○ ActivityManagerService(AMS,运行在刚启动的 system_server 进程中)需要启动一个新应用时,它会向这个 Socket 发送一个连接请求和启动命令(包含要启动的 App 包名、主类名等信息)
    ○ Zygote 接收到请求后,再次调用 fork(),分裂出一个新的子进程(即应用进程)
    ○ 在子进程(应用进程)中,会处理启动参数,最终调用 ActivityThread 类的 main 方法,开始执行应用的代码
    ○ 父进程(Zygote)则继续回到 Socket 循环中,等待下一个请求。由于 fork() 的特性,Zygote 进程始终保持“纯净”,里面只有预加载好的系统资源,没有任何应用代码

总结

Zygote 的启动流程是一个经典的、分层清晰的、充分优化的设计:

  1. 由 init 进程根据配置脚本启动,确定了其基础身份和参数
  2. app_process (app_main.cpp) 作为原生入口,完成底层初始化,并搭建好通往 Java 世界的桥梁
  3. ZygoteInit 在 Java 世界完成三大核心使命:
    ○ 预加载(Preload):为快速孵化做准备(备好“干粮”)
    ○ 孵化系统服务(Fork SystemServer):生下第一个最重要的“孩子”,让它去管理整个系统
    ○ 监听请求(Socket Loop):进入“待产”状态,随时根据系统指令孵化出新的应用进程
http://www.xdnf.cn/news/1440271.html

相关文章:

  • 视频判重需求:别为同一内容花两次钱!
  • 涨了一倍多的顺丰同城,还能继续做大即时零售基建的蛋糕吗?
  • HTML5 标题标签、段落、换行和水平线
  • 光谱相机的探测器类型
  • 相机在两个机械臂上安装方式比较
  • 字节跳动后端 一面凉经
  • 单片机:GPIO、按键、中断、定时器、蜂鸣器
  • 知微传感Dkam系列3D相机SDK例程篇:CSharp连接相机及保存数据
  • Debezium日常分享系列之:Debezium 3.3.0.Alpha2发布
  • Gemini CLI源码解析:Agent与上下文管理实现细节
  • Airsim 笔记:Python API 总结
  • ESXI8多网卡链路聚合
  • 渗透测试中的常见误区与最佳实践
  • 【LeetCode 热题 100】72. 编辑距离——(解法一)记忆化搜索
  • DBSCAN 密度聚类分析算法
  • 【ProtoBuf 】C++ 网络通讯录开发实战:ProtoBuf 协议设计与 HTTP 服务实现
  • 构建下一代互联网:解码Web3、区块链、协议与云计算的协同演进
  • 【微信小程序预览文件】(PDF、DOC、DOCX、XLS、XLSX、PPT、PPTX)
  • 机器学习进阶,一文搞定模型选型!
  • 智能高效内存分配器测试报告
  • 根据fullcalendar实现企业微信的拖动式预约会议
  • Linux 用户的 Windows 改造之旅
  • Web端最强中继器表格元件库来了!55页高保真交互案例,Axure 9/10/11通用
  • 使用langgraph创建工作流系列3:增加记忆
  • 100种高级数据结构 (速查表)
  • 【NVIDIA B200】1.alltoall_perf 单机性能深度分析:基于 alltoall_perf 测试数据
  • 如何评价2025年数学建模国赛?
  • Debezium系列之:Flink SQL消费Debezium数据,只消费新增数据,过滤掉更新、删除数据
  • 计算机毕业设计选题推荐:基于Python+Django的新能源汽车数据分析系统
  • AI随笔番外 · 猫猫狐狐的尾巴式技术分享