Zygote工作流程分析

Zygote工作流程分析

Zygote

      接收客户端创建进程的请求,使用JNI调用linux fork函数创建进程。

Zygote是在Init进程中作为Service被启动的。Zygote进程的主体是:ZygoteInit。

      Zygote进程的启动可以参考前篇:Android系统启动过程

http://www.cnblogs.com/bastard/archive/2012/08/28/2660389.html

系统启动过程如下图:


下面主要看看Zygote是如何进行工作的。

一 Zygote工作流程

主函数:

复制代码
publicstaticvoid main(String argv[]) {       ……       // Registers a server socket for zygote command connections    registerZygoteSocket();        /**       * Runs the zygote process's select loop. Accepts new connections as       * they happen, and reads commands from connections one spawn-request's       * worth at a time.       */       runSelectLoopMode();    //loop中}
复制代码


消息循环是runSelectLoopMode

复制代码
privatestaticvoidrunSelectLoopMode() throws MethodAndArgsCaller {
    … …       while(true) {              int index;              //异步方式 获取ZygoteConnection Command              fdArray = fds.toArray(fdArray);              index = selectReadable(fdArray);
if(index == 0) {                     //读取新的ZygoteConnection Socket                     ZygoteConnection newPeer = acceptCommandPeer();                     peers.add(newPeer);                     fds.add(newPeer.getFileDesciptor());              } else {                     //处理ZygoteConnection Commandboolean done;                     done = peers.get(index).runOnce();                    }            }}
复制代码

过程如下图所示:




1 ZygoteConnection Command 接收

在ZygoteInit的 main函数中

复制代码
publicstaticvoid main(String argv[]) {    ……    // Registers a server socket for zygote command connections  registerZygoteSocket();    /**    * Runs the zygote process's select loop. Accepts new connections as    * they happen, and reads commands from connections one spawn-request's    * worth at a time.    */    runSelectLoopMode();    //loop中} //registerZygoteSocket注册了Server 端Socket监听ZygoteConnection:
privatestaticvoid registerZygoteSocket() {       //” ANDROID_SOCKET_zygote”       String env = System.getenv(ANDROID_SOCKET_ENV);      fileDesc = Integer.parseInt(env);        //private static LocalServerSocket sServerSocket;if (sServerSocket == null) {              sServerSocket = new LocalServerSocket(                     createFileDescriptor(fileDesc));       }}
复制代码

  使用到了LocalServerSocket进行通信,具体如何进行请看源码。


2 ZygoteConnection Command处理

  在循环中done = peers.get(index).runOnce();――> ZygoteConnection runOnce


复制代码
boolean runOnce( ) {       Arguments parsedArgs = null;       FileDescriptor[] descriptors;       //Reads one start command from the command socket.       args = readArgumentList();       descriptors = mSocket.getAncillaryFileDescriptors();       //创建/Forks a new VM instance /process.       //使用Jni 调用nativeFork       pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,              parsedArgs.gids, parsedArgs.debugFlags, rlimits);       //返回两次if (pid == 0) {              // in child                  serverPipeFd = null;              handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);              // should never get here, the child is expected to eitherreturntrue;       } else {              // in parent...pid of < 0 means failure              childPipeFd = null;              return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);       }}
复制代码


3 Zygote创建新进程的执行

从上面的代码中可以看到创建进程之后返回:

      子进程:handleChildProc

      父进程:handleParentProc

我们关心的是子进程的执行,继续到handleChildProc中。

复制代码
// Handles post-fork setup of child procprivatevoid handleChildProc(Arguments parsedArgs,...){       ……       if (parsedArgs.runtimeInit) {           if (parsedArgs.invokeWith != null) {        //通过系统调用执行进程WrapperInit.execApplication(parsedArgs.invokeWith,          parsedArgs.niceName, parsedArgs.targetSdkVersion,          pipeFd, parsedArgs.remainingArgs);           } else {        //通过寻找到相应目标类的main()函数并执行RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,          parsedArgs.remainingArgs);           }       }       ……}
复制代码


看到子进程的执行有两种方式:

  WrapperInit.execApplication和RuntimeInit.zygoteInit

1)通过系统调用的方式执行进程 WrapperInit.execApplication

复制代码
publicstaticvoid execApplication(……) {  ……  Zygote.execShell(command.toString());}publicstaticvoid execShell(String command) {  // using the exec() system callnativeExecShell(command);}
复制代码



2)通过寻找到相应目标类的main()函数并执行 RuntimeInit.zygoteInit:

复制代码
// The main function called when started through the zygote process.publicstaticfinalvoid zygoteInit( ){        zygoteInitNative();        applicationInit(targetSdkVersion, argv);}privatestaticvoid applicationInit( ) {        // Remaining arguments are passed to the start class's static main        invokeStaticMain(args.startClass, args.startArgs);}
通过RuntimeInit调用startClass的main函数。
复制代码


  为何两种方式?可以参考下面文章:

http://blog.csdn.net/21cnbao/article/details/7791254

  以上是Zygote大概简要的工作流程,要深入了解进程创建过程还不行,以上两种方式执行新创建的进程有何区别,

还得熟悉Android,Linux 及其Fork的一些知识和原理。

  linux fork可以参考我转载的文章:

http://www.cnblogs.com/bastard/archive/2012/08/31/2664896.html

  了解了Zygote大概工作流程,如果我们要创建进程该如何告知Zygote呢?

在StartActivity如果是启动新的应用就会创建该应用的进程,下面我们可以看一下StartActivity时创建进程的过程。


二 应用程序进程的创建过程

      启动一个新的应用程序为例,启动新的应用程序时候是以startActivity的方式进行,这个过程大致如下图:



  在启动应用程序的时需要创建应用程序的进程,执行到:

  ActivityManagerService的startProcessLocked函数中;看一下这个函数过程:

复制代码
privatefinalvoid startProcessLocked(ProcessRecord app,    String hostingType, String hostingNameStr){  // Start the process.  It will either succeed and return a result containing  // the PID of the new process, or else throw a RuntimeException.  Process.ProcessStartResult startResult =  Process.start("android.app.ActivityThread",                   app.processName, uid, uid, gids, debugFlags,                   app.info.targetSdkVersion, zygoteArgs);}
复制代码



  到了Process这个类:Tools for managing OS processes.

复制代码
publicstaticfinal ProcessStartResult start(…… ) {       return startViaZygote(processClass, niceName, uid, gid, gids,                    debugFlags, targetSdkVersion, zygoteArgs);}//Starts a new process via the zygote mechanism.privatestatic ProcessStartResult startViaZygote(…… ){       synchronized(Process.class) {              ArrayList<String> argsForZygote = new ArrayList<String>();              //参数设置              // --runtime-init, --setuid=, --setgid=,……        //--runtime-init这里决定上面所提到创建新的进程的启动方式              argsForZygote.add("--runtime-init");                       argsForZygote.add("--setuid=" + uid);              argsForZygote.add("--setgid=" + gid);              //……              argsForZygote.add(processClass);              for (String arg : extraArgs) {                  argsForZygote.add(arg);              }                 return zygoteSendArgsAndGetResult(argsForZygote);       }}
复制代码



复制代码
//Sends an argument list to the zygote process, which starts a new child//and returns the child's pidprivatestatic ProcessStartResult zygoteSendArgsAndGetResult    (ArrayList<String> args){       //open socket to Zygote process if not already open       openZygoteSocketIfNeeded();       //write Argument       sZygoteWriter.write(Integer.toString(args.size()));       sZygoteWriter.newLine();       sZygoteWriter.flush();       ……}
复制代码

通过上面这一段代码,向Zygote发送创建进程的请求,设置相关的参数。

其中有argsForZygote.add("--runtime-init");    决定新创建进程的启动方式为RuntimeInit.zygoteInit方式启动:

找到目标类main函数执行。

processClass"android.app.ActivityThread",将是进程创建之后执行的类,执行其中的main函数。

联系上面的流程:

创建进程后执行到RuntimeInit.zygoteInit:(直接找到目标类的main函数调用不是系统调用)

复制代码
// The main function called when started through the zygote process.publicstaticfinalvoid zygoteInit( ){        applicationInit(targetSdkVersion, argv);}privatestaticvoid applicationInit( ) {//后将执行:ActivityThread的main函数,启动界面。       invokeStaticMain(args.startClass, args.startArgs);}
复制代码


ActivityThread就是应用程序的主线程的入口。


  以上便是Zygote工作流程和启动应用程序创建进程大概简单过程,其中所涉及到知识和框架比较多,还需要去理解linux fork知识和原理,

进程概念,Android进程通信机制Binder,Activity启动过程等。这里仅简单的从代码上做流程分析。

  参考文档:

http://blog.csdn.net/luoshengyang/article/details/6689748


你可能感兴趣的:(android,Zygote)