谈谈对Android中Zygote的理解

174 阅读7分钟

一、概述

Android 操作系统是基于Linux内核的,内核启动后,首先会加启动用户空间的第一个进程,也就是init进程,最后会调用/system/core/init/init.cpp的main()函数,它是init的入口函数。

init.cpp

  int main(int argc, char** argv) {
    if (is_first_stage) {
        ...
        //创建文件并挂载
        mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
        mkdir("/dev/pts", 0755);
        mkdir("/dev/socket", 0755);
        mount("devpts", "/dev/pts", "devpts", 0, NULL);
        #define MAKE_STR(x) __STRING(x)
        mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));
        // Don't expose the raw commandline to unprivileged processes.
        chmod("/proc/cmdline", 0440);
        gid_t groups[] = { AID_READPROC };
        setgroups(arraysize(groups), groups);
        mount("sysfs", "/sys", "sysfs", 0, NULL);
        mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
        ...
    }
    ...
    //初始属性相关资源
    property_init();
    ...
    //启动属性服务
    start_property_service();
    ...
    //解析init.rc配置文件
    LoadBootScripts(am, sm);
    ...
    return 0;
  }

总结init进程的主要工作:

  1. 创建和挂载启动所需要的文件和目录。
  2. 初始化和启动属性服务。
  3. 通过解析init.rc 和 其他对应rc文件,启动相应的系统级进程,其中就包括Zygote进程。

init.rc

import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc
...

再来看看zygote.rc配置文件(以init.zygote32.rc为例)

init.zygote32.rc

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc reserved_disk
    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

这段配置文件要求init进程创建一个名为zygote的进程,该进程要执行的程序是/system/bin/app_process,并且未zygote进程创建一个socket资源(用于进程间通信,ActivityManagerService就是通过socket请求zygote进程 fork一个应用程序进程)。 后面的“--zygote”是传给app_process的参数,表示启动的是zygote进程,会执行app_main.cpp里面的main()函数。

二、Zygote启动流程

上面已经讲述Zygote进程是如何启动的了;Zygote进程是如何从Native世界到Java世界的?

2.1 Zygote的Native世界

从上面分析我们知道Zygote启动会调用app_main.cpp里面的main()函数;

app_main.cpp

int main(int argc, char* const argv[]){
    ...
    //解析启动Zygote进程传递的参数
    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;
    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }
    ...
    //通过runtime启动zygote
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    }
    ...
}

真正由Native世界到java世界是通过AndroidRuntime的start函数;

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote){
    ...
     /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    //开启虚拟机
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);
    
    /*
     * Register android functions.
     */
     //注册系统JNI函数
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
    ...
    //找到ZygoteInit的main函数,通过JNI调用,Zygote进入java框架层
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
}

2.2 Zygote Java世界 ZygoteInit.java

这张时序图就是Zygote进程的创建流程,结合代码看一看。

  public static void main(String argv[]) {
       //1、创建ZygoteServer
        ZygoteServer zygoteServer = new ZygoteServer();
      .......
        try {
             .......
            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
           // 2、解析app_main.cpp传来的参数
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    enableLazyPreload = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }

            if (abiList == null) {
                throw new RuntimeException("No ABI list supplied.");
            }
            //3、创建一个Server端的Socket
            zygoteServer.registerServerSocket(socketName);
            // In some configurations, we avoid preloading resources and classes eagerly.
            // In such cases, we will preload things prior to our first fork.
            if (!enableLazyPreload) {
                bootTimingsTraceLog.traceBegin("ZygotePreload");
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                    SystemClock.uptimeMillis());
               //4、加载进程的资源和类
                preload(bootTimingsTraceLog);
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                    SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            } else {
                Zygote.resetNicePriority();
            }
              ........
            if (startSystemServer) {
                //5、开启SystemServer进程,这是Zygote进程的第一次分裂
                startSystemServer(abiList, socketName, zygoteServer);
            }

            Log.i(TAG, "Accepting command socket connections");
           //6、启动一个死循环监听来自Client端的消息
            zygoteServer.runSelectLoop(abiList);
           //7、关闭SystemServer的Socket
            zygoteServer.closeServerSocket();
        } catch (Zygote.MethodAndArgsCaller caller) {
            // 8、运行MethodAndArgsCaller的run方法
            caller.run();
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            zygoteServer.closeServerSocket();
            throw ex;
        }
    }

ZygoteInit的main方法大概就做了上面六件事情:

  1. 创建ZygoteServer。
  2. 解析app_main.cpp传来的参数。
  3. 创建一个Server端的Socket,作用是当Zygote进程将SystemServer进程启动后,就会在这个Socket上来等待ActivityManagerService请求,创建我们自己App应用程序进程。
  4. 预加载类和资源,包括颜色啊,R文件,drawable、类等。
  5. 启动SystemServer进程,这是上层Framework的运行载体,ActivityManagerService就是运行在这个进程里面的。
  6. 开启一个循环,等待着接收ActivityManagerService的请求创建新的应用程序进程。

三、SystemServer

SystemServer进程主要用于创建系统服务,我们熟悉的AMS、WMS、PMS都是由它来创建的。

在前面讲过,Zygote进程启动了SystemServer进程,启动部分代码码:

private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        ...
        ZygoteConnection.Arguments parsedArgs = null;
        int pid;
        try {
            parsedArgs = new ZygoteConnection.Arguments(args);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

            boolean profileSystemServer = SystemProperties.getBoolean(
                    "dalvik.vm.profilesystemserver", false);
            if (profileSystemServer) {
                parsedArgs.runtimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
            }

            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.runtimeFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        //判断是否是SystemServer进程
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            //关闭Zygote的Socket
            zygoteServer.closeServerSocket();
            //启动SystemServer进程
            return handleSystemServerProcess(parsedArgs);
        }

        return null;
    }

fork()函数:在Linux系统内,创建子进程的方法是使用系统调用fork()函数,fork()函数调用一次会得到两个返回值: 函数返回值:

  1. 0 表示子进程
  2. 大于0 父进程,返回值为创建出的子进程的PID
  3. -1 出错 fork函数用于从一个已经存在的进程创建一个新进程,新的进程称为“子进程”,相应的创建子进程的进程为“父进程”。使用fork函数得到的子进程是父进程的复制品,子进程完全复制了父进程的资源,包括进程上下文、代码区、堆栈区、内存信息等等。 由于SystemServer进程是Zygote进程fork出来的,当返回值 pid为0 的时候就代表创建的是SystemServer进程,SystemServer也会有一个zygoteServer所开启的Socket实例副本,在这里并不需要这个Socket,所以关闭。

接下来看下handleSystemServerProces()方法。

/**
     * Finish remaining work for the newly forked system server process.
     */
    private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
        ...
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                //在这里创建了PathClassLoader
                cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
                Thread.currentThread().setContextClassLoader(cl);
            }

            /*
             * Pass the remaining arguments to SystemServer.
             */
              //zygoteInit方法
            return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
       ...
    }

接下里看看zygoteInit方法。

public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
       ...
       //启动了Binder线程池
       ZygoteInit.nativeZygoteInit();
       //进入SystemServer的main方法
       return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
   }
   
   virtual void onZygoteInit()
   {
       sp<ProcessState> proc = ProcessState::self();
       ALOGV("App process: starting thread pool.\n");
       proc->startThreadPool();
   }

nativeZygoteInit是Native层的代码,用来启动Binder线程池,这样SystemServer进程就可以使用Binder与其他进程进行通信了。

applicationInit方法,用于启动SystemServer。

protected static void applicationInit(int targetSdkVersion,String[] argv,ClassLoader classLoader){
  ...
  invokeStaticMain(args.startClass,args.startArgs,classLoader);
}

...

private static void invokeStaticMain(String className,String[] argv,ClassLoader classLoader){
  Class<?> cl;
  ...
  
  //className是com.android.server.SystemServer
  cl=Class.forName(className,true,classLoader);
  ...
  //找到SystemServer的main方法
  m=cl.getMethod("main",new Class[]{String[].class});
  ...
  // 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.
  //抛出异常,这里抛出异常中调用了SystemServer的main方法
  throw new Zygote.MethodAndArgsCaller(m,argv);
}

在invokeStaticMain方法最后,以抛出异常的方式调用了SystemServer的main方法,(之后在启动其他应用进程的时候,也是这里调用ActivityThread的main方法的)。这种处理会清除所有设置过程需要的堆栈信息。

/**
* Helper exception class which holds a method and arguments and
* can call them. This is used as part of a trampoline to get rid of
* the initial process setup stack frames.
*/
public static class MethodAndArgsCaller extends Exception
      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);
      }
  }
}

这个功能比较单一,是协助反射调用的,调用了run方法将通过反射调用传入的方法。

接下来解析下SystemServer进程做了什么。

public static void main(String[] args){
   //就一行代码
   new SystemServer().run();
}

private void run(){
   ...
   //创建消息Looper
   Looper.prepareMainLooper();
   //加载动态库
   System.loadLibrary("android_servers");
   //创建SystemServiceManager
   mSystemServiceManager=new SystemServiceManager(mSystemContext);
   ...
   //启动引导服务
   startBootstrapServices();
   //启动核心服务
   startCoreServices();
   //启动其他服务
   startOtherServices();
   ...
}

SystemServer.java

在SystemServer进程中陆续启动了各种服务,包括ActivityManagerService、PowerManagerService、PackageManagerService等等,而这些服务的父类都是SystemService。

最后总结一下SystemServer进程:

  1. 启动Binder线程池。
  2. 创建了SystemServiceManager(用于对系统服务进行创建、启动和生命周期管理)。
  3. 启动了各种服务。