精华内容
下载资源
问答
  • Zygote

    万次阅读 2016-08-01 17:24:09
    在Android中,zygote是整个系统创建新进程的核心装置。zygote进程在内部会先启动Dalvik虚拟机,继而加载一些必要的系统资源和系统类,最后进入一种监听状态。  在之后的运作中,当其他系统模块(比如AMS)希望创建...

    相关源码:

    /frameworks/base/cmds/app_process/App_main.cpp (内含AppRuntime类)
    /frameworks/base/core/jni/AndroidRuntime.cpp
    /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
    /frameworks/base/core/java/com/android/internal/os/Zygote.java
    /frameworks/base/core/java/android/net/LocalServerSocket.java

             

             在Android中,zygote是整个系统创建新进程的核心进程。zygote进程在内部会先启动Dalvik虚拟机,继而加载一些必要的系统资源和系统类,最后进入一种监听状态。

             在之后的运作中,当其他系统模块(比如AMS)希望创建新进程时,只需向zygote进程发出请求,zygote进程监听到该请求后,会相应地fork出新的进程,于是这个新进程在初生之时,就先天具有了自己的Dalvik虚拟机以及系统资源。

             zygote进程是由init进程启动起来,由init.rc 脚本中关于zygote的描述可知:zygote对应的可执行文件就是/system/bin/app_process,也就是说系统启动时会执行到这个可执行文件的main()函数里。

    service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
        class main
        socket zygote stream 660 root system
        onrestart write /sys/android_power/request_state wake
        onrestart write /sys/power/state on
        onrestart restart media
        onrestart restart netd
    

    【解析】

    zygote作为一个名字标识了这个service(可执行程序);

    /system/bin/app_process表示可执行文件的位置;

    class、user、group、onrestart这些关键字所对应的行都被称为options, options是用来描述的service一些特点,不同的service有着不同的options。

    第三行表示在Zygote启动过程中,要在其内部创建一个名为zygote的socket,它在Linux下的权限是666,即所有用户多可以对它进行读写。

           下面看一个Zygote的启动流程图:


    一、Zygote启动函数调用类的栈关系:
    App_main.main
          AndroidRuntime.start
               startVm
               startReg
               ZygoteInit.main
                     registerZygoteSocket
                     preload
                     startSystemServer
                     runSelectLoop

           zygote服务的main()函数位于frameworks\base\cmds\app_process\App_main.cpp。关键代码如下:

    int main(int argc, char* const argv[])
    {
        . . . . . .
        AppRuntime runtime;
        const char* argv0 = argv[0];    // -Xzygote
        argc--;
        argv++;
        . . . . . .
        int i = runtime.addVmArguments(argc, argv);
        . . . . . .
        while (i < argc) {
            const char* arg = argv[i++];		// 应该是/system/bin目录
            if (!parentDir) {
                parentDir = arg;
            } else if (strcmp(arg, "--zygote") == 0) {
                zygote = true;
                niceName = "zygote";
            } else if (strcmp(arg, "--start-system-server") == 0) {
                startSystemServer = true;
            } 
            . . . . . .
        }
    
        if (niceName && *niceName) {
            setArgv0(argv0, niceName);
            set_process_name(niceName);     // 一般改名为“zygote”
        }
        runtime.mParentDir = parentDir;
        if (zygote) {
          runtime.start("com.android.internal.os.ZygoteInit", args);
       } else if (className) {
          runtime.start("com.android.internal.os.RuntimeInit", args);
       } else {
          fprintf(stderr, "Error: no class name or --zygote supplied.\n");
          app_usage();
          LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
          return 10;
       }
    }

       

           main()函数里先构造了一个AppRuntime对象,即AppRuntime runtime;而后把进程名改成“zygote”,并利用runtime对象,把工作转交给java层的相应的***Init类处理。

          根据传入参数的不同可以有两种启动方式,一个是 "com.android.internal.os.RuntimeInit", 另一个是 ”com.android.internal.os.ZygoteInit", 对应RuntimeInit 和 ZygoteInit 两个类, 这两个类的主要区别在于Java端,可以明显看出,ZygoteInit 相比 RuntimeInit 多做了很多事情,比如说 “preload", "gc" 等等。但是在Native端,他们都做了相同的事, startVM() 和 startReg() 

    简单地说就是:Zygote进程的main()函数在启动Dalvik虚拟机后,会调用另一个ZygoteInit类的main()静态函数。

    1、 zygote在native层的调用示意图如下:

    2、 zygote在java层的调用主要是由ZygoteInit.java完成的,调用示意图如下:



       ZygoteInit.java关键代码如下(frameworks/base/core/java/com/android/internal/os/ZygoteInit.java)

    public class ZygoteInit {
    	......
    
    	public static void main(String argv[]) {
    		try {
    			......
    
    			registerZygoteSocket();
    			
    			......
    
    			......
    
    			if (argv[1].equals("true")) {
    				startSystemServer();
    			} else if (!argv[1].equals("false")) {
    				......
    			}
    
    			......
    
    			if (ZYGOTE_FORK_MODE) {
    				......
    			} else {
    				runSelectLoopMode();
    			}
    
    			......
    		} catch (MethodAndArgsCaller caller) {
    			......
    		} catch (RuntimeException ex) {
    			......
    		}
    	}
    
    	......
    }

    主要做了四件事情:

    (1)调用registerZygoteSocket函数创建了一个socket接口,用来和ActivityManagerService等通讯;

    (2)预加载一些类与资源;

    (3)调用startSystemServer函数来启动SystemServer组件;

             startSystemServer()并不是在函数体内直接调用Java类的main()函数的,而是通过抛异常的方式,在startSystemServer()之外加以处理的。

    【为什么要以异常方式启动】

    (a)首先、我们要先清楚,抛异常这一操作会引发什么? 

           我们知道,当一个函数抛出异常后,这个异常会依次传递给调用它的函数,知道这个异常被捕获,如果这个异常一直没有被处理,最终就会引起程序的崩溃。

    (b)其次、在传递异常的时候,应用程序的栈发生了什么变化? 

            这就要牵涉到函数的执行模型了,我们知道,程序都是有一个个函数组成的(除了汇编程序),c/c++/java/..等高级语言编写的应用程序,在执行的时候,他们都拥有自己的栈空间(是一种先进后出的内存区域),用于存放函数的返回地址和函数的临时数据,每调用一个函数时,就会把函数的返回地址和相关数据压入栈中,当一个函数执行完后,就会从栈中弹出,cpu会根据函数的返回地址,执行上一个调用函数的下一条指令。 

            所以,在抛出异常后,如果异常没有在当前的函数中捕获,那么当前的函数执行就会异常的退出,从应用程序的栈弹出,并将这个异常传递给上一个函数,直到异常被捕获处理,否则,就会引起程序的崩溃。

           因此,这里通过抛异常的方式启动主要是清理应用程序栈中ZygoteInit.main以上的函数栈帧,以实现当相应的main函数退出时,能直接退出整个应用程序。 当当前的main退出后,就会退回到MethodAndArgsCaller.run而这个函数直接就退回到ZygoteInit.main函数,而ZygoteInit.main也无其他的操作,直接退出了函数,这样整个应用程序将会完全退出。

    (4)调用runSelectLoopMode函数进入一个无限循环在前面创建的socket接口上等待ActivityManagerService等的请求。


    2.1 startSystemServer()

           其并不是在函数体内直接调用Java类的main()函数的,而是通过抛异常的方式,在startSystemServer()之外加以处理的。

    private static boolean startSystemServer()
            throws MethodAndArgsCaller, RuntimeException 
    {
        . . . . . .
        /* Hardcoded command line to start the system server */
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,
                            3001,3002,3003,3006,3007",
            "--capabilities=" + capabilities + "," + capabilities,
            "--runtime-init",
            "--nice-name=system_server",
            "com.android.server.SystemServer",
        };
        ZygoteConnection.Arguments parsedArgs = null;
        int pid;
        try {
            parsedArgs = new ZygoteConnection.Arguments(args);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
    
            // fork出系统服务对应的进程
            pid = Zygote.forkSystemServer(parsedArgs.uid, parsedArgs.gid,
                                                parsedArgs.gids, parsedArgs.debugFlags, null,
                                                parsedArgs.permittedCapabilities,
                                                parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }
    
        // 对新fork出的系统进程,执行handleSystemServerProcess()
        if (pid == 0) {
            handleSystemServerProcess(parsedArgs);
        }
        return true;
    }
    其中:

    (1)Zygote.forkSystemServer()会通过jni调用linux的fork函数;

    (2)startSystemServer()会在新fork出的子进程中调用handleSystemServerProgress(),进而抛出异常MethodAndArgsCaller,通过caller.run()启动com.android.server.SystemServer的main 方法。

    可参考:Systemserver


    2.2、runSelectLoop()

    private static void runSelectLoop() throws MethodAndArgsCaller 
    {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
        FileDescriptor[] fdArray = new FileDescriptor[4];
    
        fds.add(sServerSocket.getFileDescriptor());
        peers.add(null);
    
        int loopCount = GC_LOOP_COUNT;
        while (true) {
            int index;
    
            if (loopCount <= 0) {
                gc();
                loopCount = GC_LOOP_COUNT;
            } else {
                loopCount--;
            }
    
            try {
                fdArray = fds.toArray(fdArray);
                index = selectReadable(fdArray);
            } catch (IOException ex) {
                throw new RuntimeException("Error in select()", ex);
            }
    
            if (index < 0) {
                throw new RuntimeException("Error in select()");
            } else if (index == 0) {
                ZygoteConnection newPeer = acceptCommandPeer();
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
            } else {
                boolean done;
                done = peers.get(index).runOnce();
                if (done) {
                    peers.remove(index);
                    fds.remove(index);
                }
            }
        }
    }

    2.2.1、在一个while循环中,不断调用selectReadable()。

    selectReadable函数是个native函数,主要就是调用select()而已。在Linux的socket编程中,select()负责监视若干文件描述符的变化情况。内部调用select等待客户端 的连接,客户端连接上之后就会返回。
    返回值:
    <0: 内部发生错误
    =0: 该客户端第一次连接到服务端。服务端调用accept与客户 端建立连接。客户端在zygote中以ZygoteConnection对象表示。
    >0: 客户端与服务端已经建立连接,并开始发送数据。表明发送数据的客户端的index,peers.get(index)取得 发送数据客户端的ZygoteConnection对象,之后调用runOnce 函数处理具体的请求。

    2.2.2、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);
           }
    }
            从上面的代码中可以看到创建进程之后返回:
    子进程: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函数,进而以异常的方式启动新的进程。

     static void invokeStaticMain(ClassLoader loader,
                String className, String[] argv)
                throws ZygoteInit.MethodAndArgsCaller {
        ....
            /*
             * This throw gets caught in ZygoteInit.main(), which responds
             * by invoking the exception's run() method. This arrangement
             * clears up all the stack frames that were required in setting
             * up the process.
             */
            throw new ZygoteInit.MethodAndArgsCaller(m, argv);
        }





    展开全文
  • zygote

    2019-07-30 01:26:20
    NULL 博文链接:https://yishizhu.iteye.com/blog/843632
  • Zygote解析

    2021-01-03 22:15:18
    一、Zygote简介 init会创建Zygote进程,SystemServer进程和应用进程都是Zygote(孵化器)fock(复制进程)出来的。所以有必要了解下Zygote的流程。 二、Zygote启动流程 分析Zygote启动首先会调用ZygoteInit的main函数...
  • 认识Zygote

    千次阅读 2016-06-07 22:37:36
    概述zygote “受精卵”,由init进程通过解析init.zygote.rc文件而创建的,zygote所对应的可执行程序app_process,所对应的源文件是App_main.cpp,进程名为zygotezygote孵化的第一个进程是System Server,而这两个...

    概述

    在java中不同的虚拟机实例会为不同的应用分配不同内存,为了使Android系统尽快启动,使用了Zygote来预加载核心类库和一些加载时间长的类(超过1250ms),让Dalvik虚拟机共享代码,降低占用内存和启动时间。
    zygote 中文为“受精卵”,由init进程通过解析init.zygote.rc文件而创建的,zygote所对应的可执行程序app_process,所对应的源文件是App_main.cpp,进程名为zygote。zygote孵化的第一个进程是System Server,而这两个都是java世界的半边天,任何一个进程死亡都会导致Java世界的奔溃。

    4.2 zygote分析

    zygote进程由init进程根据init.rc文件中配置创建,是android系统首个java进程,是所有java进程的父进程,zygote最初名字叫“app_process”,这个名字是在Android.mk文件中指定的,但是在运行过程中Linux下的pctrl系统调用将自己名字换成了“zygote”,因此通过ps命令查看到进程名称为”zygote”.原型app_process所对应的源文件是App_main.cpp

    涉及到的函数调用

    `App_main.main
    AndroidRuntime.start
        startVm
        startReg
        ZygoteInit.main
            registerZygoteSocket
            preload
            startSystemServer
            runSelectLoop`
    

    从AndroidRuntime到ZygoteInit

    主要分为2大过程

    1、创建虚拟机——startVm:调用JNI虚拟机创建函数

    2、注册JNI函数——startReg:前面已经创建虚拟机,这里就需要给这个虚拟机注册一些JNI函数(后续java世界用到的函数是native实现,这里需要提前注册注册这些函数)

    此时就要执行CallStaticViodMethod,通过这个函数将进入android精心打造的java世界,这个函数将调用com.android.internal.os.ZygoteInit的main函数

    进入java世界

    在 ZygoteInit.main函数中进入java世界,但是这个世界啥都没与需要做很多初始化工作,主要有4个关键步骤

    1、建立IPC通信服务——registerZygoteSocket

    zygote及系统中其他程序的通信并没有使用Binder,而是采用基于AF_UNIX类型的Socket,registerZygoteSocket函数的作用正是建立这个Socket

    预加载类和资源

    主要是preloadClasses和preloadResources,其中preloadClasses一般是加载时间超过1250ms的类,因而需要在zygote预加载

    启动system_server——startSystemServer

    这个函数会创建Java世界中系统Service所驻留的进程system_server,该进程是framework的核心,也是zygote孵化出的第一个进程。如果它死了,就会导致zygote自杀。

    等待请求——runSelectLoppMode

    zygote从startSystemServer返回后,将进入第四个关键函数runSelectLoppMode,在第一个函数registerZygoteSocket中注册了一个用于IPC的Socket将在这里使用,这里Zygote采用高效的I/O多路复用机制,保证在没有客户端请求时或者数据处理时休眠,否则响应客户端的请求

    此时zygote完成了java世界的初创工作,调用runSelectLoppMode便开始休眠了,当收到请求或者数据处理便会随时醒来,继续工作

    zygote的分裂

    zygote主要用来孵化system_server进程和应用程序进程。在孵化出第一个进程system_server后通过runSelectLoopMode等待并处理消息,分裂应用程序进程仍由system_server控制,如app启动时创建子进程

    小结:

    宏观把握了zygote的诞生到创建java世界的的过程

    参考《深入理解android卷一》

    展开全文
  • Zygote总结

    2018-12-19 17:17:00
    Zygote是由init进程通过解析init.zygote.rc文件而创建的,zygote所对应的可执行程序 app_process,所对应的源文件是App_main.cpp,进程名为zygoteZygote重启的情况(四种) servicemanager进程被杀; ...

    Zygote是由init进程通过解析 init.zygote.rc 文件而创建的,zygote所对应的可执行程序 app_process,所对应的源文件是App_main.cpp,进程名为zygote。

    Zygote重启的情况(四种)

    • servicemanager进程被杀; (onresart)
    • surfaceflinger进程被杀; (onresart)
    • Zygote进程自己被杀; (oneshot=false)
    • system_server进程被杀; (waitpid)

    从App_main()开始,Zygote启动过程的函数调用类大致流程如下:

     

    Zygote采用高效的I/O多路复用机制,保证在没有客户端连接请求或数据处理时休眠,否则响应客户端的请求。

     

    时序图如下:

        整个Zygote调用流程总结

    1. 解析init.zygote.rc中的参数,创建AppRuntime并调用AppRuntime.start()方法;
    2. 调用AndroidRuntime的startVM()方法创建虚拟机,再调用startReg()注册JNI函数;
    3. 通过JNI方式调用ZygoteInit.main(),第一次进入Java世界;
    4. registerZygoteSocket()建立socket通道,zygote作为通信的服务端,用于响应客户端请求;
    5. preload()预加载通用类、drawable和color资源、openGL以及共享库以及WebView,用于提高app启动效率;
    6. zygote完毕大部分工作,接下来再通过startSystemServer(),fork得力帮手system_server进程,也是上层framework的运行载体。
    7. zygote功成身退,调用runSelectLoop(),随时待命,当接收到请求创建新进程请求时立即唤醒并执行相应工作。

     

    通过cmd命令,来fork新进程来执行类中main方法的方式:(启动后进入RuntimeInit.main)

     app_process [可选参数] 命令所在路径 启动的类名 [可选参数]
    

     

    转载于:https://www.cnblogs.com/krislight1105/p/10144570.html

    展开全文
  • android zygote

    2019-05-19 16:41:53
    所有应用进程虚拟机,都是继承zygote,共享资源,加速应用启动。 启动sevice抛出异常,在异常信号中重启zygote 和systemServer 预加载资源: 预加载作用 查看加载时间: 优化方法, 多线程 ...

    服务

    虚拟机创建流程

    虚拟机配置

    zygote启动

    分析

    所有应用进程虚拟机,都是继承zygote,共享资源,加速应用启动。

     

    启动sevice抛出异常,在异常信号中重启zygote 和 systemServer 

    预加载资源:

    预加载作用

    查看加载时间:

    优化方法,

    多线程

    BLCR技术

    上次启动成功,,并将已经加载好的资源 和 寄存器的一些信息,将这些信息保存成一个文件(blcr技术),下次启动的时候就直接加载这个文件。

    展开全文
  • Android Zygote

    2016-05-17 15:31:24
    Android Zygote
  • zygote详解

    2017-11-30 11:29:53
    在init进程详解的一章中,我们知道init.rc文件中的zygote启动脚本命令是service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server class main socket zygote stream 660 root...
  • 【Android】【Zygote】Android Zygote进程
  • Zygote进程

    2018-05-21 10:54:26
    总结:Zygote进程mian方法主要执行逻辑:初始化DDMS;注册Zygote进程的socket通讯;初始化Zygote中的各种类,资源文件,OpenGL,类库,Text资源等等;初始化完成之后fork出SystemServer进程;fork出SystemServer进程...
  • Zygote分析

    千次阅读 2017-03-19 17:53:11
    Zygote进程是通过可执行文件app_process创建的,但是app_process除了能创建Zygote进程之外,还可以创建出普通进程。 今天就来说说,Zygote都做了那些事情,这个进程创建出了那些进程。Zygote是Android系统核心进程...
  • 启动zygote

    2016-12-23 16:18:17
    在init.rc中配置zygote启动参数,使用adb pull /init.rc ,文件和zygote相关配置信息如下。 service zygote /system/bin/app_process -Xzygote 5.2 启动Socket服务端口 当zygote服务从app_process启动后,会启动一个...
  • Android Zygote分析

    2021-02-22 21:50:50
    Android Zygote Android的zygote本质上是Android的虚拟机,是Android的SystemServer和几乎所有Java应用的卵化器,它们的父进程都是zygote。没有zygote就没有Android,Android的启动也离不开zygotezygote是很重要...
  • Android Zygote解析

    2014-11-30 19:37:28
    ( Android Zygote解析
  • Android zygote

    2016-07-19 23:25:01
    zygote的作用: Android应用的神:每个应用对应一个进程,那么它们都是由zygote进程创建出来的。具体如下图: 1,linux内核启动的用户级进程 init 启动一个Zygote进程 2,Zygote创建出一个监听的进程为之...
  • zygote启动过程

    2011-11-17 23:43:49
    zygote启动过程zygote启动过程zygote启动过程zygote启动过程zygote启动过程
  • zygote启动流程

    2011-11-17 23:39:44
    zygote启动流程zygote启动流程zygote启动流程zygote启动流程zygote启动流程
  • zygote笔记

    2016-07-15 00:59:01
    新的android应用程序A并非通过fork来重新装载已有进程的代码区,而是被动的加载到复制出的Dalvik虚拟机上,Zygote进程将执行流程交给应用程序A类的方法. Zygote子进程动态加载并运行Android应用程序A 通过已加载至内存...
  • Zygote 与/dev/socket/zygote

    千次阅读 2017-06-05 16:59:32
    1、zygote socket 的创建apk的启动是ams 通过socket 与zygote 通信,然后由zygote fork出来一个进程,来加载运行apk的。 ams 与zygote 通信的socket 是在系统启动时,由init.zygote*.rc 中指定创建的:service ...
  • Android之Zygote

    2019-05-31 12:21:45
    Zygote是什么 Zygote是一个守护进程服务,SystemServer和其他所有的Dalvik虚拟机进程都是由Zygote fork出来的。 Zygote是Android中最重要的一个进程,和Init进程,SystemServer进程是支撑Android世界的三极。...
  • 作者说这是一个系列的...Zygote 的中文意思是受精卵、合子,可以理解为孵化器——Android 中大多数应用进程和系统进程都是通过 Zygote 来生成的。 PS:源码基于 Android API 27。 Zygote 是怎么启动的? init ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,826
精华内容 1,930
关键字:

zygote