Android Zygote启动(AOSP 11)

1,660 阅读4分钟

我正在参加中秋创意投稿大赛,详情请看:中秋创意投稿大赛

Android Zygote启动(AOSP 11)

AndroidRuntime.start:

接上文 Android Init启动 ,我们知道了init进程启动完成之后,会通过AndroidRuntime.start方法,加载ZygoteInit这个Java类,进行Zygote进程的启动。

Zygote的中文释义是【受精卵】,通常也叫做孵化器,是一个很贴切的名字,Android中的App应用进程以及系统关键服务进程SystemServer进程,都是通过Zygote进程进行创建的。

而Zygote进程在启动的时候,会创建一个AndroidRuntime,当通过fork调用创建一个子进程的时候,子进程便也有了一个AndroidRuntime。

ART.start最主要的作用就是通过调用指定ClassName的static void main方法,启动一个JVM:

// 第一个参数是className(非simpleName),第二个参数是要传给main的参数
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    // ...
    static const String8 startSystemServer("start-system-server");
    // Whether this is the primary zygote, meaning the zygote which will fork system server.
    bool primary_zygote = false;

    // 启动参数包含了start-system-server,就表示启动的是Zygote主模式
    for (size_t i = 0; i < options.size(); ++i) {
        if (options[i] == startSystemServer) {
            primary_zygote = true;
           /* track our progress through the boot sequence */
           const int LOG_BOOT_PROGRESS_START = 3000;
           LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
        }
    }
		// ...
    // 省略一些环境参数的设置
    // ...

    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    // startVm中通过各种参数的配置,最终调用到JNI_CreateJavaVM,创建一个JVM实例
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    onVmCreated(env);

   	// 将各种Android相关的JNI函数注册到JVM中,比如Log,Binder等等
    // 具体可以看base/core/jni/AndroidRuntime.cpp中的代码
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    // 把各种要传给main方法的参数封装好

    // 准备启动JVM了
    // 把启动的className的'.'替换为'/'
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    // 找到要启动的Class
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        // 找到要启动的Class的main方法
        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 {
            // 执行要启动的Class的main方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
    // 程序正常运行是不会走到这里的
  	// ...
}

所以ART.start做的核心事情就是:

  1. 启动一个JVM。
  2. 将android提供的JNI注册到启动的JVM中。
  3. 找到ZygoteInit这个class并执行它的main函数。

至此,Zygote的启动就从Native Framework转移到了Java Framework。

ZygoteInit:

在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java中:

public static void main(String[] argv) {
        // ...
        try {
            // ...
            boolean startSystemServer = false;
            String zygoteSocketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            for (int i = 1; i < argv.length; i++) {
                // 需要启动SystemServer
                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)) {
                    // 获取zygote进程的socket的name
                    zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }
            if (!enableLazyPreload) {
                // 预加载类和资源
                preload(bootTimingsTraceLog);
            }
            // ①核心,创建ZygoteServer对象。
            zygoteServer = new ZygoteServer(isPrimaryZygote);
            if (startSystemServer) {
                // ②核心,fork出SystemServer
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
                if (r != null) {
                    r.run();
                    return;
                }
            }
            // ③核心,开启Zygote的select循环
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }
        if (caller != null) {
            caller.run();
        }
    }

创建ZygoteServer对象如下:

   ZygoteServer(boolean isPrimaryZygote) {
        mUsapPoolEventFD = Zygote.getUsapPoolEventFD();
        if (isPrimaryZygote) {
            // 如果是主Zygote进程,那么会创建socket,socket的名字为ANDROID_SOCKET_zygote
            // 同时socket监听的最大连接数量为50
            // frameworks/base/core/java/android/net/LocalServerSocket.java
            mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
            mUsapPoolSocket =
                    Zygote.createManagedSocketFromInitSocket(
                            Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
        } else {
            // 如果是辅助Zygote进程,也是一样的
            mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
            mUsapPoolSocket =
                    Zygote.createManagedSocketFromInitSocket(
                            Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
        }

        mUsapPoolSupported = true;
        // 配置USAP相关属性,USAP是Android 10引入的新机制
        // 通过提前fork出一批进程的方式,当有新进程需要创建的时候
        // 直接将提前创建好的进程进行分配,省去了临时fork,以提高性能表现。
        fetchUsapPoolPolicyProps();
    }
    
// Zygote.createManagedSocketFromInitSocket
    static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
        int fileDesc;
        final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
        try {
            // 得到socket的环境变量的值
            String env = System.getenv(fullSocketName);
            // 转换环境变量为文件描述符参数
            fileDesc = Integer.parseInt(env);
        } catch (RuntimeException ex) {
            throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
        }
        try {
            // 创建Socket对应的文件描述符
            FileDescriptor fd = new FileDescriptor();
            fd.setInt$(fileDesc);
            // 创建LocalServerSocket对象
            return new LocalServerSocket(fd);
        } catch (IOException ex) {
            throw new RuntimeException(
                "Error building socket from file descriptor: " + fileDesc, ex);
        }
    }
    
 // impl.listen中会开启监听这个fd
 // AMS和Zygote通信是基于Socket的,后续AMS可以通过这个socket
 // 与Zygote进行通信。
 public LocalServerSocket(FileDescriptor fd) throws IOException
    {
        impl = new LocalSocketImpl(fd);
        impl.listen(LISTEN_BACKLOG);
        localAddress = impl.getSockAddress();
    }

创建并完成了Zygote作为Socket Server端Socket相关设置工作,接着看到②处的forkSystemServer:

   private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        // 省略:一些配置SystemServer的启动参数,
        // 包含比如启动类名为com.android.server.SystemServer
        int pid;
        try {
            // fork创建SystemServer进程
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }
        // pid==0表示是子进程,zygote进程的子进程即SystemServer进程
        if (pid == 0) {
            // 如果需要辅助模式的zygote进程,那么会为辅助zygote进程同样创建socket连接
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            // 因为SystemServer进程fork自Zygote进程,自然也复制了包括Zygote的socket连接
            // 但是这些连接对于SystemServer是没有作用的,因此需要关闭。
            zygoteServer.closeServerSocket();
            // 处理SystemServer进程
            return handleSystemServerProcess(parsedArgs);
        }
        return null;
    }

上面代码中,核心是Zygote.forkSystemServer,通过nativeForkSystemServer这个native调用,完成SystemServer进程的创建。nativeForkSystemServer的实现位于base/core/jni/com_android_internal_os_zygote.cpp中,核心实现就是ForkCommon中通过fork调用,创建一个进程,同时,也会做一些系统信号Handler设置工作。fork出了SystemServer进程后,在handleSystemServerProcess往后的一系列调用中,最终会找到SystemServer的Class和main方法,启动SystemServer。

继续回到ZygoteInit中:

// ③核心,开启Zygote的select循环
caller = zygoteServer.runSelectLoop(abiList);

runSelectLoop的实现如下:

    Runnable runSelectLoop(String abiList) {
        ArrayList<FileDescriptor> socketFDs = new ArrayList<>();
        // 与Zygote进程建立的链接
        ArrayList<ZygoteConnection> peers = new ArrayList<>();
        // 将Zygote进程创建的Socket(即下文提到的PRIMARY_SOCKET_NAME)
        // 添加到socketFDs中
        socketFDs.add(mZygoteSocket.getFileDescriptor());
        peers.add(null);
        mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
        // 无限循环
        while (true) {
            // ...
            int[] usapPipeFDs = null;
            StructPollfd[] pollFDs;
            // 将socetFD存储的信息保存到StructPollfd
            int pollIndex = 0;
            for (FileDescriptor socketFD : socketFDs) {
                pollFDs[pollIndex] = new StructPollfd();
                pollFDs[pollIndex].fd = socketFD;
                pollFDs[pollIndex].events = (short) POLLIN;
                ++pollIndex;
            }
            // ...
            // 等待pollFDs对应的Socket中有数据写入
          	try {
                pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }
            // ...
            if (pollReturnValue == 0) {
                // 省略
            } else {
                boolean usapPoolFDRead = false;
                while (--pollIndex >= 0) {
                    if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
                        continue;
                    }

                    if (pollIndex == 0) {
                        // pollIndex为0,则表示有进程与Zygote Socket建立连接(比如AMS),
                        // 会创建一个ZygoteConnection添加到Zygote Socket的连接池中
                        // 而connetion关联的socket就是
                        // Zygete启动过过程中创建的名字为PRIMARY_SOCKET_NAME的
                        // mZygoteSocket
                        ZygoteConnection newPeer = acceptCommandPeer(abiList);
                        peers.add(newPeer);
                        // 将ZygeteConnection的FD添加到socketFDs中,那么后面Zygote便可以
                        // 接收到AMS发送的请求。
                        socketFDs.add(newPeer.getFileDescriptor());
                    } else if (pollIndex < usapPoolEventFDIndex) {
                        // pollIndex不为0,则表示比如AMS向Zygote发送了请求
                        // 同时,可以通过USAP机制创建进程
                        try {
                            ZygoteConnection connection = peers.get(pollIndex);
                            boolean multipleForksOK = !isUsapPoolEnabled()
                                    && ZygoteHooks.isIndefiniteThreadSuspensionSafe();
                            // 内部调用Zygote的forkSimpleApp进行应用进程的创建
                            final Runnable command =
                                    connection.processCommand(this, multipleForksOK);
                          }
    // ...
    }

回看startViaZygote:

之前在 Activity启动流程分析 中,我们知道了App新进程的创建,最终是通过ZygoteProcess.startViaZygote调用完成的。现在就来看看,这个function后面坐了哪些事情:

startViaZygote如下:

// ...
// 一大堆根据入参,进行参数组装的逻辑
// 最后
synchronized(mLock) {
	// The USAP pool can not be used if the application will not use the systems graphics
	// driver.  If that driver is requested use the Zygote application start path.
	return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
		zygotePolicyFlags,
		argsForZygote);
}

zygoteSendArgsAndGetResult->attemptZygoteSendArgsAndGetResult,在zygoteSendArgsAndGetResult中会将启动参数处理成一个string,传递给attemptZygoteSendArgsAndGetResult

    private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(
            ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {
        try {
            final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
            final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;
						// 将要启动进程的各种信息,写入到zygoteWriter的buffer中。
            zygoteWriter.write(msgStr);
            // 刷新buffer
            zygoteWriter.flush();
						
            Process.ProcessStartResult result = new Process.ProcessStartResult();
            // 新进程已经创建完成了。
            result.pid = zygoteInputStream.readInt();
            result.usingWrapper = zygoteInputStream.readBoolean();

            if (result.pid < 0) {
                throw new ZygoteStartFailedEx("fork() failed");
            }

            return result;
        } catch (IOException ex) {
            zygoteState.close();
            Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "
                    + ex.toString());
            throw new ZygoteStartFailedEx(ex);
        }
    }

BufferedWriter 和 BufferedReader是带有缓冲的字符输入输出流,write的时候,将信息写入Buffer中,flush的时候,将缓冲区的数据写入到目的文件。因此我们得知道mZygoteOutputWriter到底是在往哪里写数据,

mZygoteOutputWriter是在ZygoteState对象创建的时候赋值的:

private ZygoteState(LocalSocketAddress zygoteSocketAddress,
	LocalSocketAddress usapSocketAddress,
	LocalSocket zygoteSessionSocket,
	DataInputStream zygoteInputStream,
	BufferedWriter zygoteOutputWriter,
	List<String> abiList) {
		this.mZygoteSocketAddress = zygoteSocketAddress;
		this.mUsapSocketAddress = usapSocketAddress;
		this.mZygoteSessionSocket = zygoteSessionSocket;
		this.mZygoteInputStream = zygoteInputStream;
		this.mZygoteOutputWriter = zygoteOutputWriter;
		this.mAbiList = abiList;
}

ZygoteState的创建是在ZygoteState的connect方法中:

        static ZygoteState connect(@NonNull LocalSocketAddress zygoteSocketAddress,
                @Nullable LocalSocketAddress usapSocketAddress)
                throws IOException {

            DataInputStream zygoteInputStream;
            BufferedWriter zygoteOutputWriter;
            // 创建一个LocalSocket对象
            final LocalSocket zygoteSessionSocket = new LocalSocket();

            if (zygoteSocketAddress == null) {
                throw new IllegalArgumentException("zygoteSocketAddress can't be null");
            }

            try {
                // 将LocalSocket对象连接到zygoteSocketAddress中
                // 与server端的socket建立连接
                // 底层是通过zygoteSocketAddress对应的Socket的fd建立连接
                zygoteSessionSocket.connect(zygoteSocketAddress);
                zygoteInputStream = new DataInputStream(zygoteSessionSocket.getInputStream());
                // zygoteOutputWriter写入的就是zygoteSessionSocket的输出流中。
                zygoteOutputWriter =
                        new BufferedWriter(
                                new OutputStreamWriter(zygoteSessionSocket.getOutputStream()),
                                Zygote.SOCKET_BUFFER_SIZE);
            } catch (IOException ex) {
                try {
                    zygoteSessionSocket.close();
                } catch (IOException ignore) { }

                throw ex;
            }

            return new ZygoteState(zygoteSocketAddress, usapSocketAddress,
                                   zygoteSessionSocket, zygoteInputStream, zygoteOutputWriter,
                                   getAbiList(zygoteOutputWriter, zygoteInputStream));
        }

那么我们知道了,最终mZygoteOutputWriter写入的数据将被zygoteSocketAddress对应的Socket端读取到,而zygoteSocketAddress对于64位主模式而言,是ZygoteProcess中的mZygoteSocketAddress,在ZygoteProcess的构造方法中:

mZygoteSocketAddress =
new LocalSocketAddress(Zygote.PRIMARY_SOCKET_NAME,
	LocalSocketAddress.Namespace.RESERVED);

PRIMARY_SOCKET_NAME就是"zygote"

那么PRIMARY_SOCKET_NAME这个Socket的读取是在什么时候进行的呢?回到ZygoteInit的runSelectLoop中,在其它进程比如AMS与Zygote建立连接的时候,实际上已经关联上了PRIMARY_SOCKET_NAME这个Zygote启动过程中创建的ZygoteServer对象持有的Socket对象。那么后续写入的数据,而Zygote的runSelectloop中,poll机制观察的一堆Socket的fd中,就包含了PRIMARY_SOCKET_NAME。

当有请求进程创建的数据写入到PRIMARY_SOCKET_NAME这个Socket中的时候,runSelectloop中的无限循环就会被唤醒,然后调用connection.processCommand,在其中,如果是App进程的创建,会调用到Zygote的forkSimpleApps,然后再最终通过zygote::forkApp -> zygote::ForkCommon,而ForkCommon上面也提到了,fork出一个子进程,这样,子进程就算是创建出来了,然后Zygote在把子进程的一些配置搞一搞,一个新的App进程就算是创建完成了。