Android系统启动系列3 zygote进程

一 概述

上一篇文章分析了 init 进程的整个启动流程。init 进程启动后,会解析 rc 文件,然后启动很多进程,其中很重要的一个进程就是 zygote 进程,zygote 进程又称受精卵进程, 所对应的可执行程序为 app_process,所对应的源文件是 app_main.cpp,进程名为 zygote,zygote 是 Android 系统创建的第一个 java 进程,它是所有 java 进程的父进程,zygote 进程最大意义是作为一个 Socket 的 Server 端,接收着来自四面八方的其它进程发出的进程创建请求,Android 中所有的应用进程的创建都是由一个应用进程通过 Binder 发送请求给 SystemServer 进程,SystemServer 进程再发送 Socket 消息给 zygote 进程,统一由 zygote 进程创建出来的。典型的 C/S 架构.下图为 zygote 进程在系统中的地位,其中图中红色标注为 Binder 通信方式,蓝色标注为 Socket 通信方式.

在这里插入图片描述

话说为什么 Android 系统采用这种架构呢,为什么所有进程的创建都是由 zygote 来做呢?原因有如下两点:

  • zygote 进程在启动的时候会创建一个虚拟机实例,因此通过 zygote 这个父进程,创建的子进程都会继承这个虚拟机实例,app 中的 java 代码可以得到翻译执行。
  • 进程与进程之间需要跨进程通信,由 zygote 进程作为父进程还可以获得一个 Binder 线程池,这样进程之间就可以使用 Binder 进行跨进程通信了。

基于以上两点,可以理解 zygote 进程为什么是所有应用进程的父进程的原因.

涉及到的源码路徑

/system/core/rootdir/init.rc
/system/core/init/main.cpp
/system/core/init/init.cpp
/system/core/rootdir/init.zygote64_32.rc
/frameworks/base/cmds/app_process/app_main.cpp
/frameworks/base/core/jni/AndroidRuntime.cpp
/libnativehelper/JniInvocation.cpp
/frameworks/base/core/java/com/android/internal/os/Zygote.java
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
/frameworks/base/core/java/android/net/LocalServerSocket.java
/system/core/libutils/Threads.cpp

二 zygote是如何被启动的

我们知道 init 进程启动后,会解析 init.rc 文件,然后创建和加载 service 字段指定的进程。zygote 进程就是以这种方式,被 init 进程加载并启动的。在 /system/core/rootdir/init.rc 中,通过如下引用来 load zygote 的 rc:

import /init.${ro.zygote}.rc

其中 ${ro.zygote} 由各个厂家使用,现在的主流厂家基本使用 zygote64_32,因此,我们的 rc 文件为 init.zygote64_32.rc,我们来看这个文件:

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    class main
    priority -20
    user root
    group root readproc
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks

service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload
    class main
    priority -20
    user root
    group root readproc
    socket zygote_secondary stream 660 root system
    onrestart restart zygote
    writepid /dev/cpuset/foreground/tasks

从这个 rc 文件中可以看到启动了二个进程,分别为 zygote 和 zygote_secondary,启动路徑为 /system/bin/app_process64 和 /system/bin/app_process32,对应的代码入口为:frameworks/base/cmds/app_process/app_main.cpp

三 zygote启动流程

3.1 zygote启动时序图

在这里插入图片描述

  1. init 进程通过解析 init.zygote64_32.rc 来启动位于 /system/bin/app_process64 的 zygote 进程,入口为 app_main.cpp
  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(),随时待命,当接收到创建新进程的请求时,立即唤醒并执行相应工作

3.2 zygote入口函数main

先来一张 zygote 在 native C 世界的代码调用图,如下:

在这里插入图片描述
frameworks/base/cmds/app_process/app_main.cpp

int main(int argc, char* const argv[])
{
	 //zygote传入的参数argv为“-Xzygote /system/bin --zygote --start-system-server --socket-name=zygote”
	 //zygote_secondary传入的参数argv为“-Xzygote /system/bin --zygote --socket-name=zygote_secondary”
	AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
	........
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
			//对于64位系统nice_name为zygote64; 32位系统为zygote
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
			 //是否需要启动system server
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
			//启动进入独立的程序模式
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
			//niceName 为当前进程别名,区别abi型号
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }
	........
	if (!className.isEmpty()) { //className不为空,说明是application启动模式
		........
	} else {
	    //进入zygote模式,新建Dalvik的缓存目录:/data/dalvik-cache
        maybeCreateDalvikCache();
		if (startSystemServer) { //加入start-system-server参数
            args.add(String8("start-system-server"));
        }
		String8 abiFlag("--abi-list=");
		abiFlag.append(prop);
		args.add(abiFlag);	//加入--abi-list=参数
		// In zygote mode, pass all remaining arguments to the zygote
		// main() method.
		for (; i < argc; ++i) {	//将剩下的参数加入args
			args.add(String8(argv[i]));
		}
	}
	........
    if (!niceName.isEmpty()) {
        //设置一个“好听的昵称” zygote\zygote64,之前的名称是app_process
        runtime.setArgv0(niceName.string(), true /* setProcName */);
    }
    if (zygote) {//如果是zygote启动模式,则加载ZygoteInit
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {//如果是application启动模式,则加载RuntimeInit
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
		//没有指定类名或zygote,参数错误
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}

zygote 本身是一个 Native 的应用程序,刚开始的进程名称为“app_process”,运行过程中,通过调用 setArgv0 将名字改为 zygote 或者 zygote64 (根据操作系统而来),最后通过 runtime 的 start() 方法来真正的加载虚拟机并进入 java 世界。

3.3 AndroidRuntime.start

frameworks/base/core/jni/AndroidRuntime.cpp

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ALOGD(">>>>>> START %s uid %d <<<<<<\n",
            className != NULL ? className : "(unknown)", getuid());
	........
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
	//虚拟机创建,主要是关于虚拟机参数的设置
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    ........ 
	// 注册JNI方法
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    } 
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr; 
	//等价 strArray= new String[options.size() + 1];
    stringClass = env->FindClass("java/lang/String");	
	//等价 strArray[0] = "com.android.internal.os.ZygoteInit"
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    classNameStr = env->NewStringUTF(className);
    env->SetObjectArrayElement(strArray, 0, classNameStr); 
	//strArray[1] = "start-system-server";
    //strArray[2] = "--abi-list=xxx";
    //其中xxx为系统响应的cpu架构类型,比如arm64-v8a.
    for (size_t i = 0; i < options.size(); ++i) {
        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
        assert(optionsStr != NULL);
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
    } 
	//将"com.android.internal.os.ZygoteInit"转换为"com/android/internal/os/ZygoteInit"
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
	//找到Zygoteinit类
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
    } else {
		//找到这个类后就继续找成员函数main方法的Mehtod ID
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
        } else {
			// 通过反射调用ZygoteInit.main()方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
        }
    }
	//释放相应对象的内存空间
    free(slashClassName);
    ALOGD("Shutting down VM\n");
    if (mJavaVM->DetachCurrentThread() != JNI_OK)
        ALOGW("Warning: unable to detach main thread\n");
    if (mJavaVM->DestroyJavaVM() != 0)
        ALOGW("Warning: VM did not shut down cleanly\n");
}

start() 函数主要做了三件事情,一调用 startVm 开启虚拟机,二调用 startReg 注册 JNI 方法,三就是使用 JNI 调用 ZygoteInit 从而进入 java 世界。

相关log:
01-10 11:20:31.369 722 722 D AndroidRuntime: >>>>>> START com.android.internal.os.ZygoteInit uid 0 <<<<<<

具体虚拟机的创建和 JNI 方法的注册本篇文章不再详细讨论,感兴趣的同学可以查看具体代码自行研究,接下来我们来分析进入 java世界的 ZygoteInit.

3.4 ZygoteInit.main

上节我们通过 JNI 调用 ZygoteInit 的 main 函数后,zygote 进程便进入了 Java 框架层,此前没有任何代码进入过 Java 框架层,换句换说zygote 开创了 Java 框架层。

在这里插入图片描述
frameworks\base\core\java\com\android\internal\os\ZygoteInit.java

public static void main(String argv[]) {
        // 1.创建ZygoteServer
        ZygoteServer zygoteServer = null; 
        // 调用native函数,确保当前没有其它线程在运行
        ZygoteHooks.startZygoteNoThreadCreation();        
        //设置pid为0,Zygote进入自己的进程组
        Os.setpgid(0, 0);
        ........
        Runnable caller;
        try {
            ........
            //得到systrace的监控TAG
            String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
            TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
                    Trace.TRACE_TAG_DALVIK);
            //通过systradce来追踪 函数ZygoteInit, 可以通过systrace工具来进行分析
            //traceBegin 和 traceEnd 要成对出现,而且需要使用同一个tag
            bootTimingsTraceLog.traceBegin("ZygoteInit"); 
            //开启DDMS(Dalvik Debug Monitor Service)功能
            //注册所有已知的Java VM的处理块的监听器。
            //线程监听、内存监听、native 堆内存监听、debug模式监听等等
            RuntimeInit.enableDdms(); 
            boolean startSystemServer = false;
            String zygoteSocketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;            
            //2. 解析app_main.cpp - start()传入的参数
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                    //启动zygote时,才会传入参数:start-system-server
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    enableLazyPreload = true;
                    //启动zygote_secondary时,才会传入参数:enable-lazy-preload
                } else if (argv[i].startsWith(ABI_LIST_ARG)) { 
                //通过属性ro.product.cpu.abilist64\ro.product.cpu.abilist32 从C空间传来的值
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
                    //会有两种值:zygote和zygote_secondary
                } else {
            throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            } 
            // 根据传入socket name来决定是创建socket还是zygote_secondary
  final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME); 
            // 在第一次zygote启动时,enableLazyPreload为false,执行preload
            if (!enableLazyPreload) {
                //systrace 追踪 ZygotePreload
                bootTimingsTraceLog.traceBegin("ZygotePreload");
                // 3.加载进程的资源和类,参考[4.2.2]
                preload(bootTimingsTraceLog);
                //systrae结束 ZygotePreload的追踪
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            } else {
                // 延迟预加载, 变更Zygote进程优先级为NORMAL级别,第一次fork时才会preload
                Zygote.resetNicePriority();
            } 
            //结束ZygoteInit的systrace追踪
            bootTimingsTraceLog.traceEnd(); // ZygoteInit
            //禁用systrace追踪,以便fork的进程不会从zygote继承过时的跟踪标记
            Trace.setTracingEnabled(false, 0);            
            // 4.调用ZygoteServer 构造函数,创建socket,会根据传入的参数,
            // 创建两个socket:/dev/socket/zygote 和 /dev/socket/zygote_secondary
            zygoteServer = new ZygoteServer(isPrimaryZygote); 
            if (startSystemServer) {
                //5.fork出system server
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer); 
                // 启动SystemServer
                if (r != null) {
                    r.run();
                    return;
                }
            } 
            // 6.zygote进程进入无限循环,处理请求
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        } 
        // 7.在子进程中退出了选择循环。继续执行命令
        if (caller != null) {
            caller.run();
        }
    }

ZygoteInit 的 main 函数主要完成了以下工作:

  • 调用 preload() 来预加载类和资源
  • 调用 ZygoteServer() 创建了两个 Server 端的 Socket 分别为 /dev/socket/zygote 和 /dev/socket/zygote_secondary,Socket 用来等待 AMS 发送过来的请求,请求 zygote 进程创建新的应用程序进程。
  • 调用 forkSystemServer 来启动 SystemServer 进程,这样系统的关键服务也会通过 SystemServer 进程启动起来。
  • 最后调用 runSelectLoop 函数来等待客户端请求

下面我们来详细来分析这四件事情。

3.5 ZygoteInit.preload

static void preload(TimingsTraceLog bootTimingsTraceLog) {
        Log.d(TAG, "begin preload"); 
        beginPreload(); // Pin ICU Data, 获取字符集转换资源等 
        //预加载类的列表---/system/etc/preloaded-classes
        //在版本:/frameworks/base/config/preloaded-classes 中,Android10.0中预计有7603左右个类
        preloadClasses(); 
        preloadResources(); //加载图片、颜色等资源文件
        //部分定义在 /frameworks/base/core/res/res/values/arrays.xml中
        ......
        preloadSharedLibraries();// 加载 android、compiler_rt、jnigraphics等library
        preloadTextResources();//用于初始化文字资源 
        WebViewFactory.prepareWebViewInZygote();//用于初始化webview;
        endPreload();//预加载完成,可以查看下面的log
        warmUpJcaProviders();
        Log.d(TAG, "end preload"); 
        sPreloadComplete = true;
    }

什么是预加载?

预加载是指在 zygote 进程启动的时候就加载,这样系统只在 zygote 执行一次加载操作,所有 app 用到该资源不需要再重新加载,减少资源加载时间,加快了应用启动速度,一般情况下,系统中 app 共享的资源会被列为预加载资源。

zygote fork 子进程时,根据 fork 的 copy-on-write 机制可知,有些类如果不做改变,甚至都不用复制,子进程可以和父进程共享这部分数据,从而省去不少内存的占用。

预加载的原理

zygote 进程启动后将资源读取出来,保存到 Resources 一个全局静态变量中,下次读取系统资源的时候优先从静态变量中查找。
frameworks/base/config/preloaded-classes:

3.6 ZygoteServer

frameworks\base\core\java\com\android\internal\os\ZygoteServer.java

class ZygoteServer {
    private LocalServerSocket mZygoteSocket;
    private LocalServerSocket mUsapPoolSocket; 
    private FileDescriptor mUsapPoolEventFD;
    //创建zygote的socket
    ZygoteServer(boolean isPrimaryZygote) {
        mUsapPoolEventFD = Zygote.getUsapPoolEventFD(); 
        if (isPrimaryZygote) {
            //创建socket,并获取socket对象,socketname: zygote
            mZygoteSocket =
                    Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
            //创建socket,并获取socket对象,socketname:usap_pool_primary
            mUsapPoolSocket =
                    Zygote.createManagedSocketFromInitSocket(
                            Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
        } else {
            //创建socket,并获取socket对象,socketname: zygote_secondary
            mZygoteSocket =
                    Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
            //创建socket,并获取socket对象,socketname: usap_pool_secondary
            mUsapPoolSocket =
                    Zygote.createManagedSocketFromInitSocket(
                            Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
        }
        fetchUsapPoolPolicyProps();
        mUsapPoolSupported = true;
    } 

frameworks/base/core/java/com/android/internal/os/Zygote.java

static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
        int fileDesc;
        // ANDROID_SOCKET_PREFIX为"ANDROID_SOCKET_" 
        //加入传入参数为zygote,则fullSocketName:ANDROID_SOCKET_zygote
        final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName; 
        try {
            //init.zygote64_32.rc启动时,指定了4个socket:
            //分别是zygote、usap_pool_primary、zygote_secondary、usap_pool_secondary
            // 在进程被创建时,就会创建对应的文件描述符,并加入到环境变量中
            // 这里取出对应的环境变量
            String env = System.getenv(fullSocketName);
            fileDesc = Integer.parseInt(env);
        } catch (RuntimeException ex) {
            throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
        } 
        try {
            FileDescriptor fd = new FileDescriptor();
            fd.setInt$(fileDesc);   // 获取zygote socket的文件描述符
            return new LocalServerSocket(fd);   // 创建Socket的本地服务端
        } catch (IOException ex) {
            throw new RuntimeException(
                "Error building socket from file descriptor: " + fileDesc, ex);
        }
    }

frameworks\base\core\java\android\net\LocalServerSocket.java

public LocalServerSocket(FileDescriptor fd) throws IOException
    {
        impl = new LocalSocketImpl(fd);
        impl.listen(LISTEN_BACKLOG);
        localAddress = impl.getSockAddress();
    }

ZygoteServer 构造函数初始化时,根据传入的参数,利用 LocalServerSocket 创建了4个本地服务端的 socket,用来建立连接。分别是:zygote、usap_pool_primary、zygote_secondary、usap_pool_secondary.

3.7 ZygoteInit.forkSystemServer

  private static Runnable forkSystemServer(String abiList, String socketName,
          ZygoteServer zygoteServer) {      
      long capabilities = posixCapabilitiesAsBits(
              OsConstants.CAP_IPC_LOCK,
              OsConstants.CAP_KILL,
              OsConstants.CAP_NET_ADMIN,
              OsConstants.CAP_NET_BIND_SERVICE,
              OsConstants.CAP_NET_BROADCAST,
              OsConstants.CAP_NET_RAW,
              OsConstants.CAP_SYS_MODULE,
              OsConstants.CAP_SYS_NICE,
              OsConstants.CAP_SYS_PTRACE,
              OsConstants.CAP_SYS_TIME,
              OsConstants.CAP_SYS_TTY_CONFIG,
              OsConstants.CAP_WAKE_ALARM,
              OsConstants.CAP_BLOCK_SUSPEND
      );
      ........
      //参数准备
      /* 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,1023,"
                      + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
              "--capabilities=" + capabilities + "," + capabilities,
              "--nice-name=system_server",
              "--runtime-args",
              "--target-sdk-version=" + VMRuntime.
SDK_VERSION_CUR_DEVELOPMENT,
              "com.android.server.SystemServer",
      };
      ZygoteArguments parsedArgs = null; 
      int pid; 
      try {
          //将上面准备的参数,按照ZygoteArguments的风格进行封装
          parsedArgs = new ZygoteArguments(args);
          Zygote.applyDebuggerSystemProperty(parsedArgs);
          Zygote.applyInvokeWithSystemProperty(parsedArgs); 
          boolean profileSystemServer = SystemProperties.getBoolean(
                  "dalvik.vm.profilesystemserver", false);
          if (profileSystemServer) {
              parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
          } 
          //通过fork"分裂"出子进程system_server
          /* Request to fork the system server process */
          pid = Zygote.forkSystemServer(
                  parsedArgs.mUid, parsedArgs.mGid,
                  parsedArgs.mGids,
                  parsedArgs.mRuntimeFlags,
                  null,
                  parsedArgs.mPermittedCapabilities,
                  parsedArgs.mEffectiveCapabilities);
      } catch (IllegalArgumentException ex) {
          throw new RuntimeException(ex);
      } 
      //进入子进程system_server
      /* For child process */
      if (pid == 0) {
          // 处理32_64和64_32的情况
          if (hasSecondZygote(abiList)) {
              waitForSecondaryZygote(socketName);
          } 
          // fork时会copy socket,system server需要主动关闭
          zygoteServer.closeServerSocket();
          // system server进程处理自己的工作
          return handleSystemServerProcess(parsedArgs);
      } 
      return null;
  } 

forkSystemServer() 会在新 fork 出的子进程中调用 handleSystemServerProcess(),主要是返回 Runtime.java 中的 MethodAndArgsCaller 方法,然后通过 r.run() 启动 com.android.server.SystemServer 的 main 函数,这个我们会在后面的分析 SystemServer 的章节中进行详细介绍,我们先看下基本调用流程

handleSystemServerProcess代码流程:
handleSystemServerProcess()
    |
    [ZygoteInit.java]
    zygoteInit()
        |
    [RuntimeInit.java]
    applicationInit()
        |
    findStaticMain()
        |
    MethodAndArgsCaller()

3.8 ZygoteServer.runSelectLoop

frameworks\base\core\java\com\android\internal\os\ZygoteServer.java

 Runnable runSelectLoop(String abiList) {
        ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>(); 
        // 首先将server socket加入到fds
        socketFDs.add(mZygoteSocket.getFileDescriptor());
        peers.add(null); 
        //无限循环用来等待AMS请求zygote创建新的应用进程
        while (true) {
            fetchUsapPoolPolicyPropsWithMinInterval(); 
            int[] usapPipeFDs = null;
            StructPollfd[] pollFDs = null; 
            // 每次循环,都重新创建需要监听的pollFds
            if (mUsapPoolEnabled) {
                usapPipeFDs = Zygote.getUsapPipeFDs();
                pollFDs = new StructPollfd[socketFDs.size() + 1 + usapPipeFDs.length];
            } else {
                pollFDs = new StructPollfd[socketFDs.size()];
            }
            int pollIndex = 0;
            for (FileDescriptor socketFD : socketFDs) {
                 // 关注事件到来
                pollFDs[pollIndex] = new StructPollfd();
                pollFDs[pollIndex].fd = socketFD;
                pollFDs[pollIndex].events = (short) POLLIN;
                ++pollIndex;
            } 
            final int usapPoolEventFDIndex = pollIndex; 
            if (mUsapPoolEnabled) {
                pollFDs[pollIndex] = new StructPollfd();
                pollFDs[pollIndex].fd = mUsapPoolEventFD;
                pollFDs[pollIndex].events = (short) POLLIN;
                ++pollIndex; 
                for (int usapPipeFD : usapPipeFDs) {
                    FileDescriptor managedFd = new FileDescriptor();
                    managedFd.setInt$(usapPipeFD); 
                    pollFDs[pollIndex] = new StructPollfd();
                    pollFDs[pollIndex].fd = managedFd;
                    pollFDs[pollIndex].events = (short) POLLIN;
                    ++pollIndex;
                }
            }
            try {
                //查询轮训状态,当pollFdd有事件到来则往下执行,否则阻塞在这里
                Os.poll(pollFDs, -1);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            } 
            boolean usapPoolFDRead = false; 
            //倒序处理,即优先处理已建立链接的信息,后处理新建链接的请求
            while (--pollIndex >= 0) {
                if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
                    continue;                } 
                // server socket最先加入fds, 因此这里是server socket收到数据
                if (pollIndex == 0) {
                    // 收到新的建立通信的请求,调用server socket端的accpet函数建立通信连接
                    // zygote进程与system server进程建立了连接
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    // 加入到peers和fds, 即下一次也开始监听
                    peers.add(newPeer);
                    socketFDs.add(newPeer.getFileDescriptor()); 
                } else if (pollIndex < usapPoolEventFDIndex) {
                    //说明接收到AMS发送过来创建应用程序的请求,调用
                    //processOneCommand来创建新的应用程序进程
                    try {
                        //有socket连接,创建ZygoteConnection对象,并添加到fds。
                        ZygoteConnection connection = peers.get(pollIndex);
                        //处理连接(用于fork新的进程)
                        final Runnable command = connection.processOneCommand(this); 
                        // TODO (chriswailes): Is this extra check necessary?
                        if (mIsForkChild) {
                            if (command == null) {
                                throw new IllegalStateException("command == null");
                            } 
                            return command;
                        } else {
                            // We're in the server - we should never have any 
                            //commands to run.
                            if (command != null) {
                                throw new IllegalStateException("command != null");
                            } 
                            if (connection.isClosedByPeer()) {
                                connection.closeSocket();
                                peers.remove(pollIndex);
                                socketFDs.remove(pollIndex);//处理完则从fds中移除该文件描述符
                            }
                        }
                    } catch (Exception e) {
                        ......
                    } finally {
                        mIsForkChild = false;
                    }
                } else {
                    //处理USAP pool的事件                    
                    long messagePayload = -1; 
                    try {
                        byte[] buffer = new byte[Zygote.USAP_MANAGEMENT_MESSAGE_BYTES];
                        int readBytes = Os.read(pollFDs[pollIndex].fd, buffer, 0, buffer.length); 
                        if (readBytes == Zygote.USAP_MANAGEMENT_MESSAGE_BYTES) {
                            DataInputStream inputStream =
                                    new DataInputStream(new ByteArrayInputStream(buffer)); 
                            messagePayload = inputStream.readLong();
                        } else {
                            continue;
                        }
                    } catch (Exception ex) {
                        if (pollIndex == usapPoolEventFDIndex) {
                        } else {
                        } 
                        continue;
                    } 
                    if (pollIndex > usapPoolEventFDIndex) {
                        Zygote.removeUsapTableEntry((int) messagePayload);
                    } 
                    usapPoolFDRead = true;
                }
            } 
            // Check to see if the USAP pool needs to be refilled.
            if (usapPoolFDRead) {
                int[] sessionSocketRawFDs =
                        socketFDs.subList(1, socketFDs.size())
                                .stream()
                                .mapToInt(fd -> fd.getInt$())
                                .toArray(); 
                final Runnable command = fillUsapPool(sessionSocketRawFDs);
                if (command != null) {
                    return command;
                }
            }
        }
}

执行 zygote 进程的循环。当来一个新的连接请求时,则建立连接,并在连接中读取请求的命令,runSelectLoop 主要分为三个部分:

  • 监听 socket 事件
    在 runSelectLoop 里面利用 while (true) 的死循环, Os.poll(pollFds, -1) 来轮询状态,如果有 pollFdd 事件来,则往下执行,否则便会阻塞在这里
  • 接受连接请求
    当 pollIndex 的值为 0 时,说明请求连接的事件来了,这时候调用 acceptCommandPeer() 来和客户端建立一个 socket 连接,然后把这个 socket 加入监听的数组中。等待这个 socket 上的命令的到来
  • 处理连接请求
    如果 pollIndex 小于 usapPoolEventFDIndex,说明是已经连接的 socket 上的命令来了。一旦接收到已和客户端连接的 socket 上传过来的命令,runSelectLoop() 方法会调用 ZygoteConnection 类 processOneCommand() 方法去处理命令。处理完后,就会断开与客户端的连接,并把用于连接的 socket 从监听表中移除。

小结:zygote 采用高效的 I/O 多路复用 epoll 机制,保证没有客户端连接请求或数据处理时休眠,否则响应客户端的请求。总体来说 runSelectLoop 方法的内部还是比较简单的,就是处理客户端的连接和请求,其中客户端在 zygote 进程中使用 ZygoteConnection 对象表示。客户端的请求由 ZygoteConnection 的 processOneCommand 来处理。

3.9 ZygoteConnection.processOneCommand

Runnable processOneCommand(ZygoteServer zygoteServer) {
    ...
    //fork子进程
    pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
            parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
            parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
            parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion);
    if (pid == 0) {
        //子进程执行
        zygoteServer.setForkChild();
        //进入子进程流程
        return handleChildProc(parsedArgs, descriptors, childPipeFd,
                parsedArgs.mStartChildZygote);
    } else {
        //父进程执行
        // In the parent. A pid < 0 indicates a failure and will be handled in 
        //handleParentProc.
        handleParentProc(pid, descriptors, serverPipeFd);
        return null;
    }
    ...
}

可以看到在 processOneCommand 中调用了 fork 用来创建一个新的进程,然后进入子进程调用 handleChildProc 函数.

3.10 ZygoteConnection.handleChildProc

private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, boolean isZygote) {
      ........
      if (parsedArgs.mInvokeWith != null) {
          ........
          throw new IllegalStateException("WrapperInit.execApplication 
unexpectedly returned");
      } else {
          if (!isZygote) {
              // App进程将会调用到这里,执行目标类的main()方法
              return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                      parsedArgs.mRemainingArgs, null /* classLoader */);
          } else {
              return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
                      parsedArgs.mRemainingArgs, null /* classLoader */);
          }
      }
  } 

3.11 ZygoteInit.zygoteInit

public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
        if (RuntimeInit.DEBUG) {
            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
        }
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        RuntimeInit.redirectLogStreams();//日志重定向
        RuntimeInit.commonInit();//通用的初始化工作
        ZygoteInit.nativeZygoteInit();//zygote初始化
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);//应用的初始化
    }

需要重点介绍下 zygoteInit 这个函数,这个函数是在 fork 后的子进程中执行的,我们知道在 fork system server 进程后,会在子进程 system server 中执行 handleSystemServerProcess 这个方法,需要注意的是在这个方法中也会调用 zygoteInit 这个函数,接下来我们来看这个函数中主要做了那些工作,以致于如此重要.其中 redirectLogStreams 是日志的重定向,而 commonInit 是通用的初始化工作,在此不做详细介绍,重点介绍 ZygoteInit.nativeZygoteInit 和 RuntimeInit.applicationInit

3.11.1 ZygoteInit.nativeZygoteInit

private static final native void nativeZygoteInit();

它是一个 native 方法,对应的是 AndroidRuntime.cpp 的 com_android_internal_os_ZygoteInit_nativeZygoteInit,最终调用到 app_main.cpp 的 onZygoteInit 代码如下:

virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();//创建ProcessState
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();//开启线程池
    }

从第一行代码中可以看到创建了 ProcessState 对象,我们之前分析 Binder 的过程中已经知道,在创建 ProcessState 的过程中会打开 Binder 设备并建立内存映射,第二行代码中调用了 ProcessState 的 startThreadPool 方法创建一个新的 Binder 线程,不断进行 talkWithDriver().这样我们在新的子进程中就建立了 Binder 通信机制了.这一点需要明白.

3.11.2 RuntimeInit.applicationInit

protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
        //true代表应用程序退出时不调用AppRuntime.onExit(),否则会在退出前调用
        nativeSetExitWithoutCleanup(true);
        //设置虚拟机的内存利用率参数值为0.75
        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
        final Arguments args = new Arguments(argv);
        // The end of of the RuntimeInit event (see #zygoteInit).
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        //调用startClass的static方法 main()
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }

此处 findStaticMain 的参数 args.startClass 为 android.app.ActivityThread"

3.11.3 findStaticMain

protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        Class<?> cl;
        try {
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }
        Method m;
        try {
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        }
        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }
        return new MethodAndArgsCaller(m, argv);
    }
static class MethodAndArgsCaller implements Runnable {
        /** method to call */
        private final Method mMethod;

        /** argument array */
        private final String[] mArgs;

        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }

        public void run() {
            try {
                mMethod.invoke(null, new Object[] { mArgs });
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                Throwable cause = ex.getCause();
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else if (cause instanceof Error) {
                    throw (Error) cause;
                }
                throw new RuntimeException(ex);
            }
        }
    }

该方法最终返回一个 MethodAndArgsCaller,这是一个 Runnable,在这个 Runnable 中会通过反射调用 ActivityThread 的 main() 方法.这个 Runnable 会一路返回到 ZygoteInit 类的 main() 方法中,代码如下:

public static void main(String argv[]) {
        ........
        Runnable caller;
        try {
            ........
            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
                // child (system_server) process.
                if (r != null) {
                    r.run();
                    return;
                }
            }
            ........
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }
        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            caller.run();//最终执行这个Runnable
        }
    }

最终会在子进程中通过 caller.run 来执行这个 Runnable,从而完成 ActivityThread main方法的执行.

四 总结

  • 解析 init.zygote64_32.rc,创建 AppRuntime 对象,并且调用其 start 函数.zygote 的核心初始化都在 AppRuntime 中。
  • 在 AndroidRuntime 的 start 方法中调用 startVm 创建 Java 虚拟机,然后调用 startReg 来注册 JNI 函数
  • 通过 JNI 调用 com.android.internal.os.ZygoteInit 的 main 函数,从此进入了 Java 世界
  • 通过 ZygoteServer 创建服务端 Socket,预加载常用的类、资源等
  • 调用 forkSystemServer 函数 fork 一个 system_server 进程来为 Java 框架服务
  • 调用 runSelectLoop 来让自己无限循环等待,等待 AMS 的进程创建请求
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值