深入研究源码:Android10.0系统启动流程(三):Zygote

12,154 阅读9分钟

前言

研究过程中参考了很多的文章,这篇源码分析,可能是全网最全的Zygote源码分析了

如果觉得这篇源码分析太,也可以先看一下后续的相关总结,戳juejin.cn/post/684490…

全文概览

我们都知道Android中非特殊进程(除init进程和Zygote进程外的进程,源码中称其为unspecialized app process),都是由Zygotefork出来的子进程,包括SystemServer,也是由Zygote fork出来的

这篇文章我们主要来探讨以下几个问题

  1. Zygote进程是如何启动的?
  2. Zygote又是如何fork出SystemServer的?
  3. 其他普通进程又是通过什么方式被fork出来的?
  4. 跟普通的App process有什么区别?

这些问题我们在接下来的源码分析中来找找答案

具体源码分析

Zygote进程是如何被启动起来的

我们首先来看下,Zygote进程是如何被启动起来的

我们还是首先从init.rc中引用的zygote.rc中入手来看,源码中是找不到的,我们从编译好的文件中找

WORKING_DIRECTORY/out/target/product/generic_x86/root/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
    socket usap_pool_primary 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 /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server 从这里,我们看到zygote的可执行文件所在的位置应该是/system/bin/app_process,那源码应该也有一个app_process的目录,上次Bilibili技术分享第一期中也提到了,zygote对应的源码其实是app_process的代码

我们接着来找到

./frameworks/base/cmds/app_process/app_main.cpp 我们从app_main的入口函数来看

int main(int argc, char* const argv[])
{
    ...
    
	//创建AppRuntime,AppRuntime是AndroidRuntime的子类对象
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));  //
    // Process command line arguments
    // ignore argv[0]
    argc--;
    argv++;
    ...
    bool known_command = false;

    int i;
    for (i = 0; i < argc; i++) { 
        ...
        runtime.addOption(strdup(argv[i])); //把Zygote.rc中的参数添加到AppRuntime,也就是AndroidRuntime中
        ...
    }

    // 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.rc解析传进来的参数,进行对比
            zygote = true; //需要执行zygote的指令
            niceName = ZYGOTE_NICE_NAME; //给 nicename 赋值为zygote
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true; //为startSystemServer的标志为赋值
        } else if (strcmp(arg, "--application") == 0) {
            application = true; //根据参数判断是否为application
        } 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;
        }
    }

    Vector<String8> args;
    //如果是zygote,则className为空,所以此处实际上是判断是否为zygote的进程
    if (!className.isEmpty()) { //判断非zygote模式时,只需要传递application的参数
        // We're not in zygote mode, the only argument we need to pass
        // to RuntimeInit is the application argument.
        //
        // The Remainder of args get passed to startup class main(). Make
        // copies of them before we overwrite them with the process name.
        args.add(application ? String8("application") : String8("tool"));
        runtime.setClassNameAndArgs(className, argc - i, argv + i);

        if (!LOG_NDEBUG) {
          String8 restOfArgs;
          char* const* argv_new = argv + i;
          int argc_new = argc - i;
          for (int k = 0; k < argc_new; ++k) {
            restOfArgs.append("\"");
            restOfArgs.append(argv_new[k]);
            restOfArgs.append("\" ");
          }
          ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string());
        }
    } else { //classname为空,当前为zygote模式
        // We're in zygote mode.
        maybeCreateDalvikCache();

        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }

        char prop[PROP_VALUE_MAX];
        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {//获取支持的CPU指令集
            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
                ABI_LIST_PROPERTY);
            return 11;
        }

        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag);

        // In zygote mode, pass all remaining arguments to the zygote
        // main() method.
        //此处为zygote模式,需要把所有参数都传递过去
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }

    if (!niceName.isEmpty()) {//niceName不为空,说明是zygote模式
        runtime.setArgv0(niceName.string(), true /* setProcName */);//此处注释也说明了,这里是设置进程名
    }

    if (zygote) {//如果是zygote模式
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);//调用zygoteInit函数,并把当前的参数传递过去
    } else if (className) {//如果是非zygote模式
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);//调用RuntimeInit函数
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}

这篇文章的目的是分析zygote的流程,那我们暂时只关心zygote相关的逻辑

函数最后调用了ZygoteInit,我们看看这个类主要做了什么

/framework/base/core/java/com/android/internal/os/ZygoteInit.java

按照之前的套路,我们先找到入口函数main

@UnsupportedAppUsage
    public static void main(String argv[]) {
        // Server socket class for zygote processes.
        ZygoteServer zygoteServer = null; //用来管理和子进程通信的socket服务端 

        // Mark zygote start. This ensures that thread creation will throw
        // an error.

        ZygoteHooks.startZygoteNoThreadCreation(); 	//这里其实只是设置一个标志位,为创建Java线程时做判断处理,如果是zygote进程,则不需要开启线程

        // Zygote goes into its own process group.
        try {
            Os.setpgid(0, 0);  //为zygote进程设置pgid(Process Group ID),详见:`https://stackoverflow.com/questions/41498383/what-do-the-identifiers-pid-ppid-sid-pgid-uid-euid-mean`
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to setpgid(0,0)", ex);
        }

        Runnable caller;
        try {
            // Report Zygote start time to tron unless it is a runtime restart
            if (!"1".equals(SystemProperties.get("sys.boot_completed"))) { //获取系统属性,判断系统重启完成
                MetricsLogger.histogram(null, "boot_zygote_init",
                        (int) SystemClock.elapsedRealtime());
            }

            String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";//判断当前进程是64位程序还是32位程序,并设置标记
            TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
                    Trace.TRACE_TAG_DALVIK);
            bootTimingsTraceLog.traceBegin("ZygoteInit");
            RuntimeInit.enableDdms();//注册到ddms服务端,内部调用`DdmServer.registerHandler()`

            boolean startSystemServer = false;
            String zygoteSocketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
			//对参数进行解析
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) { //参数重包含`start-system-server`
                    startSystemServer = true; //设置标志为位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)) {
                    zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }
			
            final boolean isPrimaryZygote =  zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);//根据socketName判断是否是primaryZygote,可能还有secondZygote

            if (abiList == null) { //如果支持架构为空,直接抛出异常
                throw new RuntimeException("No ABI list supplied.");
            }

            // 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());
                preload(bootTimingsTraceLog);
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                        SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            } else {
                Zygote.resetNicePriority();
            }

            // Do an initial gc to clean up after startup
            bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
            gcAndFinalize(); //调用ZygoteHooks.gcAndFinalize()进行垃圾回收
            bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC

            bootTimingsTraceLog.traceEnd(); // ZygoteInit
            // Disable tracing so that forked processes do not inherit stale tracing tags from
            // Zygote.
            Trace.setTracingEnabled(false, 0);


            Zygote.initNativeState(isPrimaryZygote);//jni调用初始化zygote的状态,是否为isPrimaryZygote

            ZygoteHooks.stopZygoteNoThreadCreation(); //结束zygote创建,其实内部是调用`runtime`给`zygote_no_threads_`赋值为false,为创建本地线程做准备

            zygoteServer = new ZygoteServer(isPrimaryZygote); //创建zygoteServer,为其他进程初始化创建时与zygote通信做准备

            if (startSystemServer) { //判断是否需要startSystemServer
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);//通过fork的方式开启zygote的子进程,systemServer,并返回一个Runnale对象
                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
                // child (system_server) process.
                if (r != null) {//如果是zygote进程,则r==null,如果不是zygote进程,也就是systemServer进程,则执行下面的代码
                    r.run();
                    return;
                }
            }

            Log.i(TAG, "Accepting command socket connections");

            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            caller = zygoteServer.runSelectLoop(abiList); //zygote进程进入死循环中,来获取子进程发送的消息
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket(); //如果发生异常,则说明zygote初始化失败,zygoteServer也需要关闭
            }
        }

        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            caller.run();
        }
    }

zygote的大概流程我们已经梳理完了,现在我们来总结一下

  1. 解析对应的zyogte.rc脚本
  2. 调用app_process/appMain.cpp
  3. 设置进程名为zygote
  4. 调用zygoteInit.java初始化zygote进程
  5. JNI调用zygoteInit.cpp完成进程创建
  6. 调用runSelectionLoop(),接收其他进程发送的消息创建子进程

Zygote是如何fork出SystemServer的

我们都知道,Android系统中,zyogte进程是Java世界的首个进程(init进程为头号进程),是直接通过exec的系统调用创建的,其他的进程,包括system_server,都是zygote进程的子进程,那我们接下来从源码的角度来看一下,zygote是如何forksystem_server

public static void main(String argv[]) {
						...
            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不为空,说明是system_server进程
                    r.run(); //调用其run方法
                    return;
                }
            }

            ...
        }
				...
    }

由上面的分析我们看到,根据zygote.rc的参数,解析出是否需要startSystemServer,如果为true,则调用forkSystemServer来fork出子进程SystemServer,并且执行其返回的Runnable的run()方法,我们先来看看forkSystemServer具体做了什么

    /**
     * Prepare the arguments and forks for the system server process.
     * 为forkSystemServer进程准备参数,并且创建system server进程
     *
     * @return A {@code Runnable} that provides an entrypoint into system_server code in the child
     * process; {@code null} in the parent.
     */
    private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
		//Linux使用POSIX capabilities代替传统的信任状模型
        long capabilities = posixCapabilitiesAsBits( //设置进程权能
                OsConstants.CAP_IPC_LOCK, //允许锁定共享内存片段
                OsConstants.CAP_KILL, //允许对不属于自己的进程发送信号
                OsConstants.CAP_NET_ADMIN, // 允许执行网络管理任务:接口、防火墙和路由等
                OsConstants.CAP_NET_BIND_SERVICE, //允许绑定到小于1024的端口
                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, //允许配置TTY设备
                OsConstants.CAP_WAKE_ALARM,
                OsConstants.CAP_BLOCK_SUSPEND
        );
        /* Containers run without some capabilities, so drop any caps that are not available. */
        StructCapUserHeader header = new StructCapUserHeader(
                OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
        StructCapUserData[] data; //用户权能数据
        try {
            data = Os.capget(header); //获取进程权能,存储到data中
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to capget()", ex);
        }
        capabilities &= ((long) data[0].effective) | (((long) data[1].effective) << 32);

        /* Hardcoded command line to start the system server */
        /*使用硬编码的方式定义出启动system server的参数字符串args*/
        String args[] = {
                "--setuid=1000", //用户id
                "--setgid=1000",//用户组id
                "--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", //进程niceName
                "--runtime-args", 
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT, 
                "com.android.server.SystemServer",
        };
        ZygoteArguments parsedArgs = null; 

        int pid; //processId,进程id

        try {
            
            parsedArgs = new ZygoteArguments(args);  ////创建ZygoteArguments对象,把args解析为需要的参数
            Zygote.applyDebuggerSystemProperty(parsedArgs);
            Zygote.applyInvokeWithSystemProperty(parsedArgs);

            boolean profileSystemServer = SystemProperties.getBoolean(
                    "dalvik.vm.profilesystemserver", false);  //跟Art虚拟机相关,暂时不做深究
            if (profileSystemServer) { 
                parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
            }

            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer( //fork创建SystemServer
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) { //pid为0,则说明是zygote进程,进行最后的收尾工作
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

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

        return null;
    }

代码最后调用了Zygote.forkSystemServer()来创建SystemServer,我们接着来跟一下

public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        ZygoteHooks.preFork();//内部调用ART的Runtime对zygote的线程池的线程进行清理
        // Resets nice priority for zygote process.
        resetNicePriority();
        int pid = nativeForkSystemServer(   //JNI调用,真正创建systemServer进程的函数
                uid, gid, gids, runtimeFlags, rlimits,
                permittedCapabilities, effectiveCapabilities);
        // Enable tracing as soon as we enter the system_server.
        if (pid == 0) {
            Trace.setTracingEnabled(true, runtimeFlags);
        }
        ZygoteHooks.postForkCommon();
        return pid;
    }

接着跟下去,到c++的本地代码中 zygote.cpp

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 permitted_capabilities,
        jlong effective_capabilities) {
  ...

  pid_t pid = ForkCommon(env, true,
                         fds_to_close,
                         fds_to_ignore);//从zygote进程fork出子进程,并返回processId
  ...
  return pid;
}

到这里我们就把相关源码分析完了,我们来总结下:

  1. 解析zygote.rc的相关脚本,获取startSystemserver的属性字段
  2. 调用startSystemServer()
  3. 调用forkSystemServer(),为当前进程赋予权限,并设置UID,GID
  4. 创建ZygoteArgument,调用zygote.forkSystemServer
  5. JNI调用native的函数,nativeForkSystemServer完成进程的fork工作

普通进程(UASP--unspecialized app process),是通过什么方式被fork出来的

这里我们只分析zygote相关的源码,完整流程等分析AMS时一起总结

zygoteInit中,最后调用了zyogteServer的runSelectionLoop()函数,进入一个无限循环中,我们来看下代码

Runnable runSelectLoop(String abiList) { //此处使用了selcet IO复用机制,这个我们以后专门来分析Linux的IO复用机制
            ...

            while (--pollIndex >= 0) {
                ...

                if (pollIndex == 0) {
                    // Zygote server socket

                    ZygoteConnection newPeer = acceptCommandPeer(abiList);//创建socket连接的服务端
                    peers.add(newPeer);
                    socketFDs.add(newPeer.getFileDescriptor());

                } else if (pollIndex < usapPoolEventFDIndex) {
                    // Session socket accepted from the Zygote server socket

                    try {
                        ZygoteConnection connection = peers.get(pollIndex); //获取到客户端连接对象ZygoteConnection
                        final Runnable command = connection.processOneCommand(this);  //读取一个sokcet命令,并fork出子进程,执行子进程的main函数

                        // TODO (chriswailes): Is this extra check necessary?
                        if (mIsForkChild) {
                            // We're in the child. We should always have a command to run at this
                            // stage if processOneCommand hasn't called "exec".
                            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");
                            }

                            // We don't know whether the remote side of the socket was closed or
                            // not until we attempt to read from it from processOneCommand. This
                            // shows up as a regular POLLIN event in our regular processing loop.
                            if (connection.isClosedByPeer()) {
                                connection.closeSocket();
                                peers.remove(pollIndex);
                                socketFDs.remove(pollIndex);
                            }
                        }
                    }
                    ...
            }

            ...
        }
    }

这里当pollIndex==0先调用acceptCommandPeer()创建sokcet连接的服务端,其他条件下,调用acceptCommandPeer()获取一个ZygoteConnect对象,并执行其processOneCommand()函数,读取一个sokcet命令,并fork出子进程,执行子进程的main函数,我们还是接着跟一下这个函数

Runnable processOneCommand(ZygoteServer zygoteServer) {
        String args[];
        ZygoteArguments parsedArgs = null;
        FileDescriptor[] descriptors;

        try {
            args = Zygote.readArgumentList(mSocketReader); //从sokcet中读取参数

            // TODO (chriswailes): Remove this and add an assert.
            descriptors = mSocket.getAncillaryFileDescriptors(); //获取其附带的文件描述符
        } catch (IOException ex) {
            throw new IllegalStateException("IOException on command socket", ex);
        }
        ...
        int pid = -1;
        FileDescriptor childPipeFd = null;//子进程,使用管道进行进程间通信,
        FileDescriptor serverPipeFd = null;

        parsedArgs = new ZygoteArguments(args); //创建Zygote参数对象
        ...
		
        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);
                //Forks a new VM instance
                //创建一个新的VM实例对象,也就是我们平时说的沙盒隔离机制(sandbox)

        try {
            if (pid == 0) {
                // in child
                zygoteServer.setForkChild();//设置标志位mIsForkChild为true
                ...
                return handleChildProc(parsedArgs, descriptors, childPipeFd,
                        parsedArgs.mStartChildZygote); //处理子进程的创建
            } else {    
                // In the parent. A pid < 0 indicates a failure and will be handled in
                // handleParentProc.
                IoUtils.closeQuietly(childPipeFd);
                childPipeFd = null;
                handleParentProc(pid, descriptors, serverPipeFd);//如果pid>0,则为子进程设置进程号,否则就是创建失败
                return null;
            }
        } finally {
            IoUtils.closeQuietly(childPipeFd);
            IoUtils.closeQuietly(serverPipeFd);
        }
    }

这里根据传递过来的参数创建zygoteArgs对象,并创建出VM虚拟机对象,最终调用handleChildProc()来创建子进程,继续跟踪代码

    private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors,
            FileDescriptor pipeFd, boolean isZygote) {
        ...

        if (parsedArgs.mNiceName != null) { //判断mNiceName不为空
            Process.setArgV0(parsedArgs.mNiceName); //设置mNiceName为进程名
        }

        // End of the postFork event.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        if (parsedArgs.mInvokeWith != null) { //判断参数中mInvokeWith为空时,使用exec的系统调用开启进程
           ...
        } else {
            if (!isZygote) { //非zygote模式
                return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mRemainingArgs, null /* classLoader */);
            } else { //zygote模式
                return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mRemainingArgs, null /* classLoader */); //zygoteInit的备选函数,同时初始化Zygote进程
            }
        }
    }

此处我们只关心由Zyogte进程fork出子进程的情况,跟踪zygoteInit()这个函数

public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
        ...
        RuntimeInit.commonInit(); //对runtime进行初始化
        ZygoteInit.nativeZygoteInit(); //JNI调用,nativeZygoteInit
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);//找到Appde 主函数并初始化调用
    }

这里首先的对Runtime进行初始化,然后通过JNI对zygote进行真正的初始化操作,函数代码如下

static AndroidRuntime* gCurRuntime = NULL;
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit(); //调用AndroidRuntime的zygoteInit
}

这里是调用了AndroidRuntimeonZygoteInit(),此处点进去可以看到它是一个虚函数,那么应该是由的子类对象来做的具体实现,之前我们也分析过,AndroidRuntimeapp_processapp_main中又一个子类对象AppRuntime,我们来看一下

public:
    AppRuntime(char* argBlockStart, const size_t argBlockLength)
        : AndroidRuntime(argBlockStart, argBlockLength)
        , mClass(NULL)
    {
    }
    ...
    virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();//开启Bind线程池线程,设置线程名称
    }
    ...
};

此处创建了一个ProcessState的对象,并调用了它的startThreadPool()函数,跟踪下去可以发现内部调用了spawnPooledThread的函数来创建线程并启动的

void ProcessState::spawnPooledThread(bool isMain)
{
    if (mThreadPoolStarted) { //判断线程已开启
        String8 name = makeBinderThreadName(); //创建Binder线程池名称
        ALOGV("Spawning new pooled thread, name=%s\n", name.string());
        sp<Thread> t = new PoolThread(isMain); //创建主线程
        t->run(name.string()); //执行线程
    }
}

handleChildProc()这一系列代码执行完毕后,会调用handleParentProc()对子进程创建状态进行判断,如果pid>0则说明创建成功,到此处我们子进程以及其相关线程就准备完毕了

现在来总结下

  1. 调用runSelectLoop,循环读取消息
  2. 调用acceptCommandPeer创建Sokcet服务端的连接对象ZygoteConnection
  3. 调用acceptOneCommand读取Soket的消息
  4. 解析参数,并创建虚拟机实例对象
  5. 调用handleChildProcess处理子进程的创建
  6. 调用zygoteInit.zyogteInit(args...)把参数传递进去
  7. 调用native方法,进行最终的初始化
  8. 回调到app_process/app_main.cppAppRuntime具体实现中
  9. 开启Binder线程池,完成子进程创建

额外加餐

ZygoteServer源码

上面我们分析Zygote流程时涉及到一个类,ZygoteServer,下面我们来具体看下,它是如何创建的

在zygote的main函数中是这么初始化的

zygoteServer = new ZygoteServer(isPrimaryZygote);

那我们就从这个构造函数入手

/**
     * Initialize the Zygote server with the Zygote server socket, USAP pool server socket, and USAP
     * pool event FD.
     *
     * @param isPrimaryZygote  If this is the primary Zygote or not.
     */
    ZygoteServer(boolean isPrimaryZygote) {
        mUsapPoolEventFD = Zygote.getUsapPoolEventFD();

        if (isPrimaryZygote) { //根据zygote.rc中的参数判断是否是PrimaryZygote
            mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);//把PRIMARY_SOCKET_NAME赋值给mZygoteSocket
            mUsapPoolSocket =
                    Zygote.createManagedSocketFromInitSocket(
                            Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);//把USAP_POOL_PRIMARY_SOCKET_NAME赋值给mUsapPoolSocket
        } else {
            mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);//把SECONDARY_SOCKET_NAME赋值给mZygoteSocket
            mUsapPoolSocket =
                    Zygote.createManagedSocketFromInitSocket(
                            Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);//把USAP_POOL_SECONDARY_SOCKET_NAME赋值给mUsapPoolSocket
        }

        fetchUsapPoolPolicyProps();

        mUsapPoolSupported = true;
    }

上面的代码里主要是把zygote.rc中的配置取出来,其中涉及到了两个socket,mZygoteSocketmUsapPoolSocket;也涉及到两个Zygote,PrimaryZygoteSecondZygote

但是你可能会奇怪,咱们的zygote.rc中,怎么没有这个东西呢?我再把这个文件贴一遍

WORKING_DIRECTORY/out/target/product/generic_x86/root/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
    socket usap_pool_primary 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

唯一跟primary有关的,是socket usap_pool_primary stream 660 root system,那SecondZygote去哪了呢?

这个跟咱们编译的版本是有关系的,当前编译的版本中,只支持32为的应用,所以只有32位的PrimaryZygote,那咱们来看一下我根据源码编译的Pixel 2的Android10系统中有没有

使用adb shell 查看

cat 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 reserved_disk
    socket zygote stream 660 root system
    socket usap_pool_primary 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 reserved_disk
    socket zygote_secondary stream 660 root system
    socket usap_pool_secondary stream 660 root system
    onrestart restart zygote
    writepid /dev/cpuset/foreground/tasks

这里很清楚的看得到,64位的zygote是PrimaryZygote,32位的zygote是SecondZygote,不同的二进制文件可以由不同的Zygote启动,同时兼容64位和32位程序

我们再来看看上面提到的两个Socket是干什么的

    /**
     * Listening socket that accepts new server connections.
     */
    private LocalServerSocket mZygoteSocket;

    /**
     * The name of the unspecialized app process pool socket to use if the USAP pool is enabled.
     */
    private LocalServerSocket mUsapPoolSocket;
    
    ...
    ZygoteServer(boolean isPrimaryZygote) {
        ...
        mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
        mUsapPoolSocket = Zygote.createManagedSocketFromInitSocket(Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
        ...
    }

这里两个sokcet的对象的创建都调用的同一个函数createManagedSocketFromInitSocket()


    /** Prefix prepended to socket names created by init */
    private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
    
    /**
     * Creates a managed LocalServerSocket object using a file descriptor
     * created by an init.rc script.  The init scripts that specify the
     * sockets name can be found in system/core/rootdir.  The socket is bound
     * to the file system in the /dev/sockets/ directory, and the file
     * descriptor is shared via the ANDROID_SOCKET_<socketName> environment
     * variable.
     */
    static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
        int fileDesc;
        final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;//拼接为socket的全路径名
        try {
            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); //把获取到的fileDesc设置进去
            return new LocalServerSocket(fd); //返回该Socket对象
        } catch (IOException ex) {
            throw new RuntimeException(
                "Error building socket from file descriptor: " + fileDesc, ex);
        }
    }

我们使用adb来查看下,很容易的查看到两个Zygote相关的socketFd

ZygoteHooks相关源码

我们来简单补充一点zygoteHooks的源码分析,分析这个问题的目的在于,理清出Dalvik和ART在Android10源码中的关系

上面的源码分析中,有几个地方调用 ZygoteHooks的相关源码,我们来简单分析下

ZygoteHooks.startZygoteNoThreadCreation() && ZygoteHooks.stopZygoteNoThreadCreation()

我们发现这个ZygoteHooks其实是ART包下的

./art/runtime/native/dalvik_system_ZygoteHooks.cc

static void ZygoteHooks_startZygoteNoThreadCreation(JNIEnv* env ATTRIBUTE_UNUSED,
                                                    jclass klass ATTRIBUTE_UNUSED) {
  Runtime::Current()->SetZygoteNoThreadSection(true);
}

可以看到这个函数是一个JNI的接口,内部调用了RuntimeSetZygoteNoThreadSection函数

./art/runtime/runtime.h

// Whether zygote code is in a section that should not start threads.
bool zygote_no_threads_;

void SetZygoteNoThreadSection(bool val) {
    zygote_no_threads_ = val;
}

bool IsZygoteNoThreadSection() const {
    return zygote_no_threads_;
}

可以看到这里其实就是设置了一个标志为,源码注释中也说明了,该字段是为了区分处于zygote模式时,不去开启线程,那我们来看看这个zygote_no_threads_的字段哪里使用到了

./art/runtime/runtime.cc

Runtime::Runtime()
    : ...
      zygote_no_threads_(false),
      ...
      {
      ...
          
      }

这里在Runtime构造初始化时,首先把其设置为false,也就是默认情况下,Runtime是会去开启线程的

再来看看返回zygote_no_threads_IsZygoteNoThreadSection()这个函数在哪里有使用

./art/runtime/native/java_lang_Thread.cc

static void Thread_nativeCreate(JNIEnv* env, jclass, jobject java_thread, jlong stack_size,
                                jboolean daemon) {
  // There are sections in the zygote that forbid thread creation.
  Runtime* runtime = Runtime::Current();
  if (runtime->IsZygote() && runtime->IsZygoteNoThreadSection()) {//判断是zygote进程,并且IsZygoteNoThreadSection()返回值为true时
    jclass internal_error = env->FindClass("java/lang/InternalError");
    CHECK(internal_error != nullptr);
    env->ThrowNew(internal_error, "Cannot create threads in zygote");//直接抛出异常,
    return; //结束当前函数
  }

  Thread::CreateNativeThread(env, java_thread, stack_size, daemon == JNI_TRUE);//如果不是zygote进程,才去创建本地线程
}

这里又是一个JNI的接口函数,是用来创建本地线程的(根据类名和方法名也可以猜到),注释中也做了说明,只有不是zygote进程时才会去创建本地线程

stopZygoteNoThreadCreation()函数也是一样,同样是设置标志为,设置为false,那么就可以去创建线程了

写在最后

这里我们基本上把zygote涉及的相关源码分析完了,下篇文章讲会对SystemServer的相关源码进行分析。由于水平有限,写的不对的还请各位多多指教

原创不易,坚持更难。

如果你想继续看到我接下来的分享,请通过点赞的方式告诉我,你的鼓励是我继续创作的最大动力!