android 学习之 zygote作用
Zygote作用
1.启动SystemServer
Zygote准备好一些常用类,JNI函数,主题资源,共享库
2.孵化应用进程
因此, 在Android中, 应用程序运行前, 通过Zygote进程共享已运行的虚拟机的代码与内存信息, 缩短应用程序运行所耗费的时间. 也就是说, Zygote进程会事先将应用程序要使用的Android Framework中的类与资源加载到内存中, 并组织形成所用资源的链接信息. 这样, 新运行的Android应用程序在使用所需资源时不必每次形成资源的链接信息, 这样就大大提升了程序的运行时间.
Zygote进程起到了预加载资源和类到虚拟机 加快启动应用程序的作用
android大致的启动三段式
进程启动 -> 准备工作 -> loop循环(接收消息,处理消息 socket,messagequeue消息,binder驱动发来的消息)
1.zygote 启动流程
Init 进程。
init.rc 定义了一些要启动的服务, zygote是其一
红色 服务 名称 , 蓝色 文件路径 , 橙色 启动参数
fork 函数 复制父进程给子进程,返回pid=0位子进程
调用app_main.cpp的main函数中的AppRuntime的start方法来启动Zygote进程
信号处理SIGCHLD
2.启动之后
Zygote的native世界
启动android虚拟机->注册Android的JNI函数->进入java世界
Zygote的java世界
preload resources->fork SystemServer 然后进入loop等待SystemServer的socket消息
【注意】
zygote fork时单线程,为了避免造成死锁或者状态不一致等问题
跨进程通信采用socket
孵化应用进程为什么不给SystemServer来做,而专门设计一个Zygote?
我们知道,应用在启动的时候需要做很多准备工作,包括启动虚拟机,加载各类系统资源等等,这些都是非常耗时的,如果能在zygote里就给这些必要的初始化工作做好,子进程在fork的时候就能直接共享,那么这样的话效率就会非常高。这个就是zygote存在的价值,这一点呢SystemServer是替代不了的,主要是因为SystemServer里跑了一堆系统服务,这些是不能继承到应用进程的。而且我们应用进程在启动的时候,内存空间除了必要的资源外,最好是干干净净的,不要继承一堆乱七八糟的东西。所以呢,不如给SystemServer和应用进程里都要用到的资源抽出来单独放在一个进程里,也就是这的zygote进程,然后zygote进程再分别孵化出SystemServer进程和应用进程。孵化出来之后,SystemServer进程和应用进程就可以各干各的事了。
Zygote的IPC通信机制为什么不采用binder?如果采用binder的话会有什么问题?
第一个原因,我们可以设想一下采用binder调用的话该怎么做,首先zygote要启用binder机制,需要打开binder驱动,获得一个描述符,再通过mmap进行内存映射,还要注册binder线程,这还不够,还要创建一个binder对象注册到serviceManager,另外AMS要向zygote发起创建应用进程请求的话,要先从serviceManager查询zygote的binder对象,然后再发起binder调用,这来来回回好几趟非常繁琐,相比之下,zygote和SystemServer进程本来就是父子关系,对于简单的消息通信,用管道或者socket非常方便省事。第二个原因,如果zygote启用binder机制,再fork出SystemServer,那么SystemServer就会继承了zygote的描述符以及映射的内存,这两个进程在binder驱动层就会共用一套数据结构,这显然是不行的,所以还得先给原来的旧的描述符关掉,再重新启用一遍binder机制,这个就是自找麻烦了。