前言 Zygote可以说是Android开发面试很高频的一道问题,但总有小伙伴在回答这道问题总不能让面试满意,在这你就要搞清楚面试问你对Zygote的理解时,他最想听到的和其实想问的应该是哪些?下面我们通过以下几点来剖析这道问题!了解Zygote的作用熟悉Zygote的启动流程深刻理解Zygote的工作原理 下面来我们来深入剖析一、Zygote的作用 Zygote的作用分为两点:启动SystemServer孵化应用进程 关于这个问题答出了这两点那就是OK了。可能大部分小伙伴可能能答出第二点,第一点就不是很清楚。SystemServer也是Zygote启动的,因为SystemServer需要用到Zygote准备好的系统资源包括: 直接从Zygote继承过来就不需要重新加载过来,那么对性能将会有很大的提升。二、Zygote的启动流程2。1启动三段式 在说Zygote启动流程之前,先明确一个概念:启动三段式,这个可以理解为Android中进程启动的常用套路,分为三步骤: 这里要了解LOOP循环是什么,其实LOOP作用是不停地接受消息,处理消息,消息的来源可以是Soket、MessageQueue、Binder驱动发过来的消息,但无论消息从哪里来,它整个流程都是去接受消息,处理消息。这个启动三段式,它不光是Zygote进程是这样的,只要是有独立进程的,比如说系统服务进程,自己的应用进程都是如此。2。2Zygote进程是怎么启动的? Zygote进程的启动取决于init进程,init进程是它是linux启动之后用户空间的第一个进程,下面看一下启动流程:linux启动init进程init进程启动之后加载init。rc配置文件 3。启动配置文件中定义的系统服务,其中Zygote服务就是定义在配置中的 4。同时启动的服务除了Zygote之外还有一些别的系统服务也是会启动的,比如说ServiceManager进程,它是通过forkexecve系统调用启动的 2。2。1加载Zygote的启动配置 在init。rc文件中会importinit。{ro。zygote}。rc,init。zygoteXX,XX指的是32或者64,对我们没差我们直接看init。zygote32。rc即可。配置文件比较长,这里做了截取保留了Zygot相关的部分。servicezygotesystembinappprocessXzygotesystembinzygotestartsystemserverclassmainsocketzygotestream660rootsystemonrestartwritesysandroidpowerrequeststatewakeonrestartwritesyspowerstateononrestartrestartaudioserverwritepiddevcpusetforegroundtasksservicezygote:是进程名称,systembinappprocess:可执行程序的路径,用于init进程fork,execve调用Xzygotesystembinzygotestartsystemserver为它的参数2。2。2启动进程 说完了启动配置呢,这里来聊一下启动进程,启动进程有两种方式: 第一种:forkhandlepidtpidfork();if(pid0){childprocess}else{parentprocess} 第二种:forkexecvepidtpidfork();if(pid0){childprocessexecve(path,argv,env);}else{parentprocess} 两者看起来差不多,首先首先都会调用fork函数创建子进程,这个函数比较奇特会返回两次,子进程返回一次,父进程返回一次。区别在于:子进程一次,返回的pid是0但是父进程返回的pid是子进程的pid,因此可以根据判断pid来区分目前是子进程还是父进程对于handle默认的情况,子进程会继承父进程的所有资源,但当通过execve去加载二进制程序时,那父进程的资源则会被清除2。2。3信号处理SIGCHLD 当父进程fork子进程后,父进程需要关注这个信号。当子进程挂了,父进程就会收到SIGCHLD,这时候父进程就可以做一些处理。例如Zygote进程如果挂了,那父进程init进程就会收到信号将Zygote进程重启。 三、Zygote进程启动原理 主要分为两部分Native层处理和Java层处理,Zygote进程启动之后,它执行了execve系统调用,它执行的是用C写的二进制的可执行程序里的main函数作为入口,然后在Java层运行! 先来看一下Native层的处理流程 在appmain。cpp文件,AndroidRuntime。cpp文件。我们可以找到几个主要函数名intmain(intargc,charargv〔〕){JavaVMjvm;JNIEnvenv;JNICreateJavaVM(jvm,(void)env,vmargs);创建Java虚拟机jclassclazzenvFindClass(ZygoteInit);找到叫ZygoteInit的Java类jmethodIDmethodenvGetStaticMethodID(clazz,Main,〔LjavalangString;)V);找到ZygoteInit类中的Main的静态函数envCallStaticVoidMethod(clazz,method,args);调用main函数jvmDestroyJavaVM();} 根据上述代码,你会发现在我们的应用里直接就可以JNI调用了,并不需要创建虚拟机。因为应用进程是Zygote进程孵化出来的,继承了父进程的拥有虚拟机,只需要重置数据即可。 接着看一下Java层的处理,具体可参考ZygoteInit文件的main方法 1。预加载资源,比如常用类库、主题资源及一些共享库等 2。启动SystemServer进程 3。进入Socket的Loop循环会看到的ZygoteServer。runSelectLoop()调用booleanrunOnce(){String〔〕argsreadArgumentList();读取参数列表intpidZygote。forkAndSpecialize();根据读取到的参数启动子进程if(pid0){inchild执行ActivityThread的入口函数(main)handleChildProc(args,。。。);returntrue;}} 四、总结 Zygote启动流程中需要主要以下2点问题Zygotefork要保证是单线程Zygote的IPC是采用socket 最后 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:点赞,转发,有你们的点赞和评论,才是我创造的动力。