zoukankan      html  css  js  c++  java
  • 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工作流程

    主函数:

    public static void 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

    private static void runSelectLoopMode() 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 Command boolean done; done = peers.get(index).runOnce(); } } }

    过程如下图所示:

          

        

          

    1 ZygoteConnection Command 接收

    在ZygoteInit的 main函数中

    public static void 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:
    private static void 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 either
                  return true;
           } 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 proc
    private void 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

    public static void execApplication(……) {
      ……
      Zygote.execShell(command.toString());
    }
    
    public static void execShell(String command) {
      // using the exec() system call
      nativeExecShell(command);
    }

     

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

    // The main function called when started through the zygote process.
    public static final void zygoteInit( ){
            zygoteInitNative();
            applicationInit(targetSdkVersion, argv);
    }
    
    private static void 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函数中;看一下这个函数过程:

    private final void 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.

    public static final ProcessStartResult start(…… ) {
           return startViaZygote(processClass, niceName, uid, gid, gids,
                        debugFlags, targetSdkVersion, zygoteArgs);
    }
    
    
    //Starts a new process via the zygote mechanism.
    private static 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 pid
    private static 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.
    public static final void zygoteInit( ){
            applicationInit(targetSdkVersion, argv);
    }
    
    private static void applicationInit( ) {
        //后将执行:ActivityThread的main函数,启动界面。
           invokeStaticMain(args.startClass, args.startArgs);
    
    }

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

     

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

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

      参考文档:

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

  • 相关阅读:
    java多线程编程(一基础概念)
    【转】android程序编译过程
    【转】什么是线程安全和线程不安全
    【转】计算机中时间的表示和存储
    【转】字符编码
    C/C++程序编译流程
    NDK学习笔记-JNI的异常处理与缓存策略
    NDK学习笔记-JNI数据类型和属性方法的访问
    NDK学习笔记-JNI数据类型和属性方法的访问
    NDK学习笔记-JNI开发流程
  • 原文地址:https://www.cnblogs.com/bastard/p/2668579.html
Copyright © 2011-2022 走看看