Zygote进程的基础流程

公众号地址/鸿洋/牛晓伟

1 Zygote 进程

Zygote 的父进程是 init 进程,Zygote 的子进程更多是我们的 APP 进程。 init 的子进程很多是后台的,Zygote 是能 native 进程中唯一能运行的 java 和 Kotlin 的

fork

Fork是什么,Fork是孵化子进程的方法,优势是快,创建一个父进程的副本,继承内存布局,环境变量,打开文件的描述符,也就是子进程和父进程会共享很多数据,内核只需要创建很少的数据就可以,还有个写时复制:共享的数据当被改变了才会拷贝复制;类似懒加载的感觉。

Zygote64 :孵化 64 位用户进程,还负责孵化systemserver
Zygote : 孵化 32 位用户进程

进程的父子关系
  • init pid=1
    • zygote pid=1222
    • zygote64 pid=1221
      • system_server
      • systemui
      • phone
      • ime
      • settings
    • init也有很多子进程
为什么不用systemsserver来fork子进程
  1. systemsserver里的数据很重要和安全的,不能给子进程共享
  2. 很多数据子进程是不需要的,会浪费,比如子进程需要自己的binder,父进程的就浪费了,
  3. zygote 干净,和提前加载JVM以及一些公共资源

2init脚本文件 zygote的出生

init进程要fork很多子进程,各不相同,就配置各自的init脚本
init.zygote64_32配置了两个服务分别孵化了zygote和zygote64

  1. zygote服务: 执行文件 /system/bin/app_process64 参数zygote --start-system-server --socket-name=zygote
  2. zygote_secondary服务:执行文件 /system/bin/app_prcess32 参数 --zygote --socket-name=zygote_secondary --enable-lazy-preload

init启动这两个服务执行两个文件,带参数都走到了 app_main.cpp的main方法

//文件路径:cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
    省略代码......
}

3zygote做了什么?

zygote职责

  1. 解析参数
  2. 启动JVM
  3. 拦截native线程创建
  4. 注册JNI方法
  5. 进入Java世界
  6. 解析参数
  7. 预加载资源
  8. 启动Systemserver进程
  9. 孵化其他app进程

参数区别

zygote 比 zygote64多一个 --enable-lazy-preload 意味不需要加载公共资源

4启动JVM

目的

启动JVM供给后续的app进程使用,这样启动更快,JVM的启动时走AppRuntime 继承AndroidRuntime

//文件路径:cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
  //构造AppRuntime实例
  AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
  
  省略代码......
  //zygote值为true
  if (zygote) {
      //调用start方法开始启动JVM,并做一些其他的初始化工作
      runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
  }
  
  省略代码......

}

启动哪种JVM

AnroidRuntime会启动前进行目录对比,检查通过后,解耦启动,就是把启动和启动哪种JVM分开,定义规范和接口
实际中,Anroid13启动是ART
jvm版本5.0后是ARt

5拦截native线程创建

Android线程

  • java线程
  • native线程
    • 纯native
    • 可调用java的native-----拦截的是他 为了做交互

可调用java代码的native线程,需要JNIEnv对象来调用java,拦截就是为把JNIev对象交给他,JNIEnv是每个进程都有的,

6注册JNI

 JNI Java Native Interface  让java能调用native

代码

例如:nativeZygoteInit 的调用

public class ZygoteInit{
    省略代码......
  
    private static native void nativeZygoteInit();
  
    省略代码......
}

//文件路径:core/jni/AndroidRuntime.cpp

const JNINativeMethod methods[] = {
        { "nativeZygoteInit", "()V",
            (void*) com_android_internal_os_ZygoteInit_nativeZygoteInit },
    };

系统中具有native功能的泪有 Parcel Binder,
此处的注册JNI方法 就是调用JNIEnv的RegisterNatives方法注册,注册后才能调用,再次注册后子进程就可以继承了

7进入Java世界

前面准备好了 就可以进入java了 ,启动JVM的时候,入口是ZygoteInit的main方法,

8解析参数

解析出来的 参数64 需要start systemserev 或者加载资源相关的,32不需要,因为32用的很少,不需要浪费

9预加载资源

加载通用的,静态的,包括各种java类,图片字体等等,供给子进程继承复用

10 启动SystemServer

前面准备好后,具备了fork能力后,第一个fork的 systemserver进程,—systemserver和 zggote进程通信是socket

为什么用socket?

binder确实更快,但是此处数据量很小 ,速度影响很小,binder不合适的点:

  1. 子进程fork要关父进程的binder
  2. 父进程的mmap的共享内存也不能复用
  3. 父进程的多进程要需要处理锁相关的,否则可能死锁
  4. 子进程后续还是需要开自己的binder
    所以此处socket更合适,systemserver作为client端,zygote是服务端,systemserver通知zygote去fork,

11 可孵化APP进程

启动systemserver进程后,就可以孵化app了!

05-19 1094
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值