android进阶之了解Zygote进程的启动及“孵化”

2022-09-08 15:44:16 浏览数 (1)

Zygote进程基础介绍

Zygote中文翻译为“受精卵”,正如其名,它主要用于孵化子进程。在Android系统中有以下两种程序: 1. java应用程序,主要基于ART虚拟机,所有的应用程序apk都属于这类 2. native程序,也就是利用C或C 语言开发的程序,如bootanimation。

所有的Java应用程序进程及系统服务SystemServer进程都由Zygote进程通过Linux的fork()函数孵化出来的,这也就是为什么把它称为Zygote的原因,因为他就像一个受精卵,孵化出无数子进程,而native程序则由Init程序创建启动。Zygote进程最初的名字不是“zygote”而是“app_process”,这个名字是在Android.mk文件中定义的。

如图所示为Zygote孵化框架:

Zygote是一个C/S模型,Zygote进程作为服务端,其他进程作为客户端向它发出“孵化”请求,而Zygote接收到这个请求后就“孵化”出一个新的进程。如图所示,当点击Launcher里的应用程序图标去启动一个新的应用程序进程时,这个请求会到达框架层的核心服务ActivityManagerService中,当AMS收到这个请求后,它通过调用Process类发出一个“孵化”子进程的Socket请求,而Zygote监听到这个请求后就立刻fork一个新的进程出来。

Zygote进程的启动

Zygote进程对应的主文件为app_main.cpp,当他被Init进程启动起来之后,就会进入主文件app_main.cpp的main()函数。接下来它的main函数开始分析Zygote进程的启动:

代码语言:javascript复制
int main(int argc, char* const argv[])
{
    .......
    while (i < argc) {
        const char* arg = argv[i  ];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            //说明启动的是Zygote进程
            niceName = ZYGOTE_NICE_NAME;
            //ZYGOTE_NICE_NAME字符串内容就是“Zygote”,此处已被换名字
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
            //在init.rc里配置了前面的这些参数,而Zygote进程启动的时候,
            //Init进程会传过来这些参数,所以此处把变量startSystemServer
            //设置为true代表启动SystemServer
        } else if (strcmp(arg, "--application") == 0) 
        .......
    }
    ......

    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
        //zygote为true代表的是Zygote进程,也就是说现在正在启动的是Zygote进程,
        //我们知道Zygote进程用于孵化子进程,Zygote进程孵化子进程是通过自己的资源赋值一份,
        //来fork一个新的子进程,也就是说子进程也会进入这个文件的main函数,因此,
        //这里的main函数被调用并不只是Zygote启动的时候被调用。这里通过zygote这个变量来区分,
        //如果是Zygote进程本身,就会进入到if里,否则就会进入到下面的else if里,代表字进程启动。
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        .......
    }
}

main()函数最后调用runtime的start()函数,runtime是一个AppRuntime对象,看看AppRuntime类:

代码语言:javascript复制
class AppRuntime : public AndroidRuntime
{
    .......
}

AppRuntime类继承AndroidRuntime类,因此前面调用的runtime的start()函数就会进入AndroidRuntime的start()函数,下面看看该函数:

代码语言:javascript复制
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ......
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    //启动VM
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

    //注册JNI函数
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android nativesn");
        return;
    }
    ....
    //className由上一步传递过来,“com.android.internal.os.ZygoteInit”或者“com.android.internal.os.RuntimeInit”
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'n", slashClassName);
    } else {
        //表明要调用的是类的main()函数
        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()函数或RuntimeInit的main()函数
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
    .......
}

AndroidRuntime的start()函数主要做了以下三件事情: 1. 调用startVM()函数启动虚拟机 2. 调用startReg()函数注册JNI方法 3. 调用com.android.internal.os.ZygoteInit类的main()函数(若是子进程,则调用com.android.internal.os.RuntimeInit的main()函数,从而基本结束初始化。而Zygote进程的main函数则还有以下的会讲到的5项工作)

下面一一介绍三个函数的具体工作:

启动虚拟机

通过调用startVM()函数启动虚拟机:

代码语言:javascript复制
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{
    ......
    //通过调用JNI_CreateJavaVM()创建虚拟机,如果对这个感兴趣,可以去研究下art虚拟机
    if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
        ALOGE("JNI_CreateJavaVM failedn");
        return -1;
    }
    ......
}

注册JNI方法

在Android中,Java世界要调用native世界的函数就要用JNI机制,并且在Android系统中也大量使用JNI机制,Android系统通过如下的startReg()函数去注册:

代码语言:javascript复制
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
    ......
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    .......
}

startReg()函数通过调用register_jni_procs()函数去进一步注册,传递的值是gRegJNI数组,原生Android6.0版本该数组超过130个,具体如下:

代码语言:javascript复制
static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_com_android_internal_os_RuntimeInit),
    REG_JNI(register_com_android_internal_os_ZygoteInit),
    REG_JNI(register_android_os_SystemClock),
    REG_JNI(register_android_util_EventLog),
    REG_JNI(register_android_util_Log),
    REG_JNI(register_android_util_MemoryIntArray),
    REG_JNI(register_android_util_PathParser),
    REG_JNI(register_android_app_admin_SecurityLog),
    REG_JNI(register_android_content_AssetManager),
    REG_JNI(register_android_content_StringBlock),
    REG_JNI(register_android_content_XmlBlock),
    REG_JNI(register_android_text_AndroidCharacter),
    REG_JNI(register_android_text_StaticLayout),
    REG_JNI(register_android_text_AndroidBidi),
    REG_JNI(register_android_view_InputDevice),
    REG_JNI(register_android_view_KeyCharacterMap),
    REG_JNI(register_android_os_Process),
    REG_JNI(register_android_os_SystemProperties),
    REG_JNI(register_android_os_Binder),
    REG_JNI(register_android_os_Parcel),
    ......
}

上面所列的JNI都通过register_jni_procs()函数来注册:

代码语言:javascript复制
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
    for (size_t i = 0; i < count; i  ) {
        if (array[i].mProc(env) < 0) {
#ifndef NDEBUG
            ALOGD("----------!!! %s failed to loadn", array[i].mName);
#endif
            return -1;
        }
    }
    return 0;
}

通过循环对所有的JNI函数进行注册。。。

调用ZygoteInit类的main()

ZygoteInit是一个Java类,我们终于走到了Java世界,看看该main()方法:

代码语言:javascript复制
    public static void main(String argv[]) {
        ......
        try {
            ......
            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            for (int i = 1; i < argv.length; i  ) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
            ........
            zygoteServer.registerServerSocket(socketName);
            .......
            preload(bootTimingsTraceLog);
            .......
            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, socketName, 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) {
            .....
        } finally {
            zygoteServer.closeServerSocket();
        }

        if (caller != null) {
            caller.run();
        }
    }

ZygoteInit类的main()方法主要做了以下5项工作: 1. 调用ZygoteServer类的registerServerSocket()方法创建一个Zygote的Socket接口,用来和AMS通信 2. 调用preload()预加载类和资源 3. 调用forkSystemServer()函数来启动SystemServer进程,r.run()启动其main()方法 4. 调用ZygoteServer类的runSelectLoop()函数在前面创建的Socket接口上进入一个无限循环,等待核心服务AMS请求创建新的应用程序进程。 5. 调用caller.run()方法,启动子进程直接进入子进程的main()方法(非system_server进程,该进程由r.run()启动main()方法)

下面一一讲解着五项工作的内容:

registerServerSocket()

通过调用ZygoteServer类的registerServerSocket()方法来创建一个Java层的LocalServerSocket对象,目的是等待创建新的应用程序进程请求:

代码语言:javascript复制
    void registerServerSocket(String socketName) {
        if (mServerSocket == null) {
            .......
            try {
                FileDescriptor fd = new FileDescriptor();
                fd.setInt$(fileDesc);
                mServerSocket = new LocalServerSocket(fd);
            } catch (IOException ex) {
                .......
            }
        }
    }
preload()预加载类与资源
代码语言:javascript复制
    static void preload(BootTimingsTraceLog bootTimingsTraceLog) {
        .......
        //加载类,通过反射加载framework下的preload-classes文件中的类
        preloadClasses();
        ......
        //加载资源,加载framework-res-apk的资源
        preloadResources();
        //这两个方法比较耗时,Android启动时间慢,这是其中一个原因,加载的类和资源太多了,导致时间过长。
        //提供一种思路去优化开机速度,既然这两个方法时间过长,就单独开一个线程去执行它,不要放在这个主线程里,可以试试
        ......
        //加载OpenGL()
        preloadOpenGL();
        .....
        //加载共享库
        preloadSharedLibraries();
        .....
    }

既然加载这些类和资源这么耗时间,为什么还要预加载: 应用程序都从Zygote孵化出来,应用程序都会继承Zygote的所有内容,如果在Zygote启动的时候加载这些类和资源,这些孵化的应用程序就继承Zygote的类和资源,这样启动引用程序的时候就不需要加载类和资源了,启动的速度就会快很多。开机的次数不多,但是启动应用程序的次数非常多。

启动SystemServer进程

后续我们将分析启动SystemServer进程,主要是比较启动SystemServer进程与启动普通应用程序进程的区别。

runSelectLoop()函数进入无限循环
代码语言:javascript复制
    Runnable runSelectLoop(String abiList) {
        .......
        while (true) {
            if (i == 0) {
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
            } else {
                ZygoteConnection connection = peers.get(i);
                final Runnable command = connection.processOneCommand(this);
                ......
        }
        .......
    }

在无限循环中,如果变量i==0,表示Zygote Socket服务还没有准备好;当i!=0时,表示正在等待客户端来连接“Zygote”这个Socket。当有孵化子进程的请求时,就会调用ZygoteConnection类的processOneCommand()函数来创建子进程。

caller.run()函数

我们将在启动应用程序进程的时候分析caller.run()函数。

SystemServer进程

启动syetem_server进程

从上面的学习可知,启动系统服务system_server进程从ZygoteInit.java的main()方法调用forkSystemServer()方法开始,先看看该方法:

代码语言:javascript复制
    private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        .....
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities="   capabilities   ","   capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",
        };
        .......
        try {
            ......
            /* 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);
        }
        .......
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }

        return null;
    }

首先设置了system_server进程的uid。gid和groups,然后设置进程的名字为”–nice-name=system_server”。接着调用forkSystemServer()函数来fork一个新的进程,他有两个返回值,一个在当前进程中返回,另一个在新创建的进程中返回,在当前进程中返回值是新创建的pid值,而新创建进程中的返回值是0。 如果pid==0,表示已经进入SystemServer子进程,于是先调用zygoteServer.closeServerSocket()关闭“Zygote”socket,由于Zygote启动过程中创建一个“Zygote”Socket。而系统服务进程system_server也继承了Socket,不用所以close它。接着调用了handleSystemServerProcess()方法:

代码语言:javascript复制
    private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
        .......
            return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        .......
    }

主要调用了ZygoteInit.zygoteInit()方法:

代码语言:javascript复制
    public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
        RuntimeInit.redirectLogStreams();

        RuntimeInit.commonInit();
        ZygoteInit.nativeZygoteInit();
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }

zygoteInit()方法主要调用了ZygoteInit.nativeZygoteInit()和RuntimeInit.applicationInit()这两个方法: - nativeZygoteInit()主要执行Binder驱动程序初始化的相关工作,它调用之后system_server进程就可以进行Binder进程通信(),是个native方法。 - 调用applicationInit()方法主要是为了进入SystemServer.java的main()方法

接下来看看RuntimeInit.applicationInit()方法:

代码语言:javascript复制
    protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
        ........
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }
代码语言:javascript复制
    private 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) {
        ..........
        return new MethodAndArgsCaller(m, argv);
    }

可以看出applicationInit()方法调用findStaticMain()方法,而该方法通过反射获取system-server的main()方法后返回一个MethodAndArgsCaller,这是一个Runnable:

代码语言:javascript复制
    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) {
            .......
            }
        }
    }

可见通过反射调用main()方法,但返回到哪呢?其实在上面的ZygoteInit类的main()方法中,在创建完system_server后直接调用,如下ZygoteInit类的main()方法代码所示,Runnable类型的r调用r.run()方法:

代码语言:javascript复制
    public static void main(String argv[]) {
        ......
        try {
            ........
            zygoteServer.registerServerSocket(socketName);
            .......
            preload(bootTimingsTraceLog);
            .......
            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, socketName, 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) {
            .....
        } finally {
            zygoteServer.closeServerSocket();
        }

        if (caller != null) {
            caller.run();
        }
    }

SystemServer fork新进程

Init进程、Zygote进程和SystemServer进程都非常重要,因为任何一个死机否会出现重启。从上面的讲解中可知,SystemServer系统服务的启动从ZygoteInit类的forkSystemServer()方法开始:

代码语言:javascript复制
    private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        .....
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities="   capabilities   ","   capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",
        };
        .......
        try {
            ......
            /* 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);
        }
        .......
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }
        return null;
    }

主要调用了两个方法,Zygote.forkSystemServer()和handleSystemServerProcess(),上面讲解了handleSystemServerProcess(),现在主要分析Zygote.forkSystemServer():

代码语言:javascript复制
    public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        VM_HOOKS.preFork();
        // Resets nice priority for zygote process.
        resetNicePriority();
        int pid = nativeForkSystemServer(
                uid, gid, gids, runtimeFlags, rlimits, permittedCapabilities, effectiveCapabilities);
        // Enable tracing as soon as we enter the system_server.
        if (pid == 0) {
            Trace.setTracingEnabled(true);
        }
        VM_HOOKS.postForkCommon();
        return pid;
    }

主要调用了nativeForkSystemServer(),这是一个native方法,对应的实现如下:

代码语言:javascript复制
static jint com_android_internal_os_Zygote_nativeForkSystemServer(
        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
        jint runtime_flags, jobjectArray rlimits, jlong permittedCapabilities,
        jlong effectiveCapabilities) {
  pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
                                      runtime_flags, rlimits,
                                      permittedCapabilities, effectiveCapabilities,
                                      MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
                                      NULL, NULL, NULL);
    //传入了众多参数来fork一个新的进程
  if (pid > 0) {
      ALOGI("System server process %d has been created", pid);
      gSystemServerPid = pid;
      int status;
      if (waitpid(pid, &status, WNOHANG) == pid) {
          ALOGE("System server process %d has died. Restarting Zygote!", pid);
          RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");
      }
  }
  return pid;
}

主要调用了ForkAndSpecializeCommon()函数:

代码语言:javascript复制
static pid_t ForkAndSpecializeCommon(......) {
    .....
    pid_t pid = fork();
    ......
    UnsetSigChldHandler();
    ......
}

主要调用了两个函数,fork()函数来创建一个新的子进程,接下来看看UnsetSigChldHandler():

代码语言:javascript复制
static void SetSigChldHandler() {
  struct sigaction sa;
  memset(&sa, 0, sizeof(sa));
  sa.sa_handler = SigChldHandler;

  int err = sigaction(SIGCHLD, &sa, NULL);
  if (err < 0) {
    ALOGW("Error setting SIGCHLD handler: %s", strerror(errno));
  }
}

SetSigChldHandler()设置了信号处理函数SigChldHandler,意思是子进程死亡之后,就会产生一个信号,Zygote进程受到该信号之后就会调用SigChldHandler()处理异常:

代码语言:javascript复制
static void SigChldHandler(int /*signal_number*/) {
  pid_t pid;
  int status;
  int saved_errno = errno;

  while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
    ........
    if (pid == gSystemServerPid) {
      kill(getpid(), SIGKILL);
    }
  }

变量gSystemServerPid表示SystemServer进程的pid,若SystemServer进程停止工作,那么首先通过getpid()来获取Zygote进程的pid,然后调用kill函数杀死它,即SystemServer停止工作之后,Zygote进程自杀,已达到Zygote与SystemServer生死与共的目的。

在Init进程的main()函数中有一个死循环,如果它的子进程Zygote停止工作,就会去重启子进程,代码如下:

代码语言:javascript复制
int main(int argc,char** argv){
    ......
    while(true){
        if(!waiting_for_exec){
            execute_one_command();
            restart_processes();
            //重启死掉的service,如果zygote死掉了,就重启Zygote。
            .......
        }
    }
}

从这个过程可知,Init进程、Zygote进程、SystemServer进程紧密相连,任何一个都不能出问题。

SystemServer创建框架核心服务

当SystemServer启动之后,就会进入main()方法,又在它的main()方法中调用run()方法。Android系统的核心服务AMS、WMS、PMS等就是在run()方法里进行创建和初始化的,当它们创建之后,会通过ServiceManager的add_server()方法把它们加入到ServiceManager中统一管理。

代码语言:javascript复制
public final class SystemServer {
    .......
    public static void main(String[] args) {
        new SystemServer().run();
    }
    ......
    private void run() {
        .....
        Looper.prepareMainLooper();
        //创建消息队列
        System.loadLibrary("android_servers");
        //加载SystemServer需要的android_servers库
        createSystemContext();
        //创建系统Context
        ......
        startBootstrapServices();
        startCoreServices();
        startOtherServices();
        //这三个方法是创建系统核心服务的实现

        Looper.loop();
        //进入消息循环,不止是应用程序有消息队列,SystemServer也有
    }
}

run()方法主要调用了三个重要的方法,在这三个方法中创建和初始化了重要的系统服务,如AMS、WMS、PMS等等。

APP应用程序进程

前面分析了Zygote如何启动SystemServer子进程,接下来再分析Zygote如何启动其他子进程,也就是创建应用程序进程的过程,这个过程和创建SystemServer进程基本一样。当点击Launcher主界面的一个应用程序图标时,如果这个应用程序还未曾启动,就会启动它。而判断应用程序有没有启动和去启动应用程序都由核心服务AMS来做,它的startProcessLocked()方法会真正地启动应用程序子进程。

下面为AMS的startProcessLocked()方法:

代码语言:javascript复制
    private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
        ......
        if (entryPoint == null) entryPoint = "android.app.ActivityThread";
        ......
        ProcessStartResult startResult;
        startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,app.info.dataDir, invokeWith, entryPointArgs);
            }
        .......
    }

AMS的startProcessLocked()方法调用Process类的start()方法为应用程序创建新的进程,这里的参数entryPoint为“android.app.ActivityThread”,它是传进去的第一个参数,也就是程序初始化进程时要加载的主文件Java类。当应用进程启动之后,会把这个类加载到进程,调用它的main()方法作为应用程序进程的入口。 Process类的start()直接调用了ZygoteProcess类的start()方法,该start()方法有直接调用了ZygoteProcess类的startViaZygote()方法,下面看看该方法实现:

代码语言:javascript复制
    private Process.ProcessStartResult startViaZygote(final String processClass,final String niceName,final int uid, final int gid,final int[] gids,int runtimeFlags, int mountExternal,int targetSdkVersion,String seInfo,String abi,String instructionSet,String appDataDir,String invokeWith,String[] extraArgs)throws ZygoteStartFailedEx {
        ArrayList<String> argsForZygote = new ArrayList<String>();
        argsForZygote.add("--runtime-args");
        argsForZygote.add("--setuid="   uid);
        argsForZygote.add("--setgid="   gid);
        ......
        synchronized(mLock) {
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
        }
    }

首先给它设置值,包括uid、gid等。这些值是应用程序在安装时系统分配好的。接着调用openZygoteSocketIfNeeded()方法来链接“zygote”Socket,链接Socket成功之后,就会调用zygoteSendArgsAndGetResult()方法来进一步处理。

先来看看openZygoteSocketIfNeeded()方法:

代码语言:javascript复制
    private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
        .......
        if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
            try {
                primaryZygoteState = ZygoteState.connect(mSocket);
            }
        .......
    }

方法中的mSocket的值是“zygote”,通过connect()方法去链接“zygote”Socket。

接着看看zygoteSendArgsAndGetResult()方法:

代码语言:javascript复制
    private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, ArrayList<String> args)
            throws ZygoteStartFailedEx {
        try {
            ........
            final BufferedWriter writer = zygoteState.writer;
            final DataInputStream inputStream = zygoteState.inputStream;

            writer.write(Integer.toString(args.size()));
            writer.newLine();

            for (int i = 0; i < sz; i  ) {
                String arg = args.get(i);
                writer.write(arg);
                writer.newLine();
            }

            writer.flush();
            .......
    }

通过Socket写入流writer把前面传过来的那些参数写进去,Socket即ZygoteServer类的runSelectLoop()方法监听。写入这些数据之后,ZygoteServer类的runSelectLoop()方法就能被监听到。 看一下runSelectLoop()方法的关键实现代码:

代码语言:javascript复制
    Runnable runSelectLoop(String abiList) {
        .......
        if (i == 0) {
            ZygoteConnection newPeer = acceptCommandPeer(abiList);
            peers.add(newPeer);
            fds.add(newPeer.getFileDesciptor());
        } else {
            ZygoteConnection connection = peers.get(i);
            final Runnable command = connection.processOneCommand(this);
        ......
    }

进入ZygoteConnection类的processOneCommand()方法后:

代码语言:javascript复制
    Runnable processOneCommand(ZygoteServer zygoteServer) {
        ........
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
                parsedArgs.appDataDir);

        try {
            if (pid == 0) {
                // in child
                zygoteServer.setForkChild();

                zygoteServer.closeServerSocket();
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;

                return handleChildProc(parsedArgs, descriptors, childPipeFd);
        ........
    }

之前启动SystemServer进程的代码有点相似。此处是通过Zygote.forkAndSpecialize()来fork新的应用进程,而启动systemserver进程是通过Zygote.forkSystemServer()来fork SystemServer进程。这里通过handleChildProc()方法处理,而之前是嗲偶用handleSystemServerProcess()来处理。通过fork新的应用程序进程之后,返回pid等于0就表示进入子进程,于是调用handleChildProc()方法进一步处理:

代码语言:javascript复制
    private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,FileDescriptor pipeFd) { 
        ........
        return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,null /* classLoader */);
        .......
    }

到此处,后面便和上面一样的了,唯一不同的是,SystemServer进程启动之后进入的是主类SystemServer.java的main()函数,而这里应用程序启动起来后进入的是主类是ActivityThread.java的main()函数。

至此,Zygote进程以及Zygote进程启动SystemServer进程和启动应用程序进程就分析完毕了,Zygote进程为了启动SystemServer和启动应用程序进程主要做了两件事,一是初始化Binder驱动用来进行进程间通信,二是通过反射进入main()方法。

0 人点赞