Zygote理解

185 阅读3分钟

init进程

  • 作用:启动关键服务、守护关键进程。
  • 关键服务:ring(铃声)、电话、蓝牙、网络、系统日志、Zygote、ServiceManager等,不包过AMS,PMS等
  • app保活,让服务变成init启动的服务。
//查看android 进程
 adb shell
 //ps 查看不到可以尝试 ps -A 或者ps -ef
 ps -ef

Zygote进程

启动Zygote进程 (由nitave进程启动的进程是native进程)
  • 作用

    • 创建一个Service端的Socket,开启LocalServiceSocket 实现进程通信
    • 加载系统类、系统资源(pp打包的时候android.jar不会被打包进去的原因)
    • 启动system_servier
    • 所有进程都是从Zygote进程中启动的,Zygote被杀死后系统会重启
  • init进程-读取 linux脚本文件->init.rc任务清单脚本文件

  • 启动Zygote进程(linux命令 service 启动的属于native进程) 1727231754669.png

  • 根据传入的参数-Xzygote app_process进程改名为zygote进程

    1727231989864.png

  • JNI启动java代码 runtime.start("com.android.internal.os.ZygoteInit", args, zygote); {AC15E909-88E7-4E20-B61D-A910BF343B51}.png

  • ZygoteInit 启动Socket实现进程间通信 用于App等相关进程启动 {C90EB62C-030F-410B-B7DC-881E060C0174}.png

  • 加载preloaded-classes文件(包含所有的app启动需要的系统源码)

{FD5C047A-B16A-47CE-9439-1BDBA1D967B9}.png

{315FE8EA-4ACA-437C-B2C4-541BE25BC9C2}.png {B80A24F7-A37F-4A91-9F27-864FA031C7B6}.png

  • 启动System_SERVER(java 进程 fork) {CDD9F4C5-1EA5-4D6B-817B-3F92A9272B40}.png

为什么Zygote通信为什么用Socket,而不是Binder? 原文链接

  1. 先后时序问题: binder驱动是早于init进程加载的。而init进程是安卓系统启动的第一个进程。 安卓中一般使用的binder引用,都是保存在ServiceManager进程中的,而如果想从ServiceManager中获取到对应的binder引用,前提是需要注册。虽然Init进程是先创建ServiceManager,后创建Zygote进程的。虽然Zygote更晚创建,但是也不能保证Zygote进程去注册binder的时候,ServiceManager已经初始化好了。注册时间点无法保证,AMS无法获取到Zygote的binder引用,这是原因之一。

image.png 2. 多线程问题 Linux中,fork进程是不推荐fork一个多线程的进程的,因为如果存在锁的情况下,会导致锁异常。 而如果自身作为binder机制的接收者,就会创建一个额外的线程来进行处理(发送者进程是无影响的)。 所以,如果使用binder机制,就会导致去fork一个多线程的进程,这是原因之二。

  1. 效率问题: AMS和Zygote之间使用的LocalSocket,相对于网络Socket,减少了数据验证等环节,所以其实效率相对于正常的网络Socket会大幅的提升。虽然还是要经过两次拷贝,但是由于数据量并不大,所以其实影响并不明显。
  2. Binder拷贝问题: 如果使用Binder机制的话,从Zygote中fork出子进程会拷贝Zygote中Binder对象。从而多占用了一块无用的内存区域。而Binder对象不能释放。Binder的特殊性在于其是成对存在的,其分为Client端对象和Server端对象。假设我们使用Binder,如果要释放掉Server端Binder引用对象,就必须释放掉AMS中的Client端Binder对象,那这样就会导致AMS失去Binder从而无法正常向Zygote发送消息。而使用Socket通讯的话,fork出APP进程之后,APP进程会去主动的关闭掉这个Socket,从而释放这块区域。使用Binder会造成额外的内存占用
  • 所有App的父进程都是Zygote ,系统类系统资源,每个App都需要,系统类都是由Zygote预加载的,防止每个App都加载一边消耗不必要资源。子进程与Zygote共享,档需要特殊操作修改时,会从内存的角度从新创建一份对应的类。