Android 8.1 zygote创建新应用进程

涉及到的文件以及路径:

frameworks/base/core/java/com/android/internal/os/Zygote.java
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

分析过Android系统启动流程的同学都知道,zygote启动之后,会调用ZygoteInit.java中的main函数。

ZygoteInit.java的路径: frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

这个main函数如下:

 public static void main(String argv[]) {// 创建一个ZygoteServer 对象,这个是8.0 之后才有的 // 这个就是zygote最后等待ActivityManager 连接来 fork新进程的地方        ZygoteServer zygoteServer = new ZygoteServer();        // Mark zygote start. This ensures that thread creation will throw        // an error.        // 调用native函数,确保当前没有其它线程在运行        // 主要还是处于安全的考虑// 启动无多线程模式 .当在zygoteInit中新建线程系统挂掉// 主要是由于担心用户新建线程提高预加载速度// 但是可能没做好同步工作, 当有的应用需要预加载的资源,但是多线程情况下还没有加载,发生问题        ZygoteHooks.startZygoteNoThreadCreation();        // Zygote goes into its own process group.// 指定当前进程的id(第一个参数是目标进程id,第二个参数是进程组id,把第二个参数设置成第一个的值)        try {            Os.setpgid(0, 0);        } catch (ErrnoException ex) {            throw new RuntimeException("Failed to setpgid(0,0)", ex);        }        final Runnable caller;        try { // 解析上面传递过来的参数            // Report Zygote start time to tron unless it is a runtime restart            if (!"1".equals(SystemProperties.get("sys.boot_completed"))) { // 如果是重启sys.boot_completed值是1                //上报Zygote进程启动的时间                MetricsLogger.histogram(null, "boot_zygote_init",(int) SystemClock.elapsedRealtime());            }            String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";            TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,Trace.TRACE_TAG_DALVIK);            bootTimingsTraceLog.traceBegin("ZygoteInit");            RuntimeInit.enableDdms();            boolean startSystemServer = false; // 是否启动 SystemServer            String socketName = "zygote";      // 创建的socket的名称            String abiList = null;             // 支持的so库的类型            boolean enableLazyPreload = false; // 这个尚不清楚,不过传递过来的参数中没有这个            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.");            }            zygoteServer.registerServerSocket(socketName); // 注册server socket            // 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();            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 process unmounts root storage spaces.// // 卸载root的存储空间            Zygote.nativeUnmountStorageOnInit();            // Set seccomp policy            // Set seccomp policy            // 加载seccomp的过滤规则            // 所有 Android 软件都使用系统调用(简称为 syscall)与 Linux 内核进行通信            // 内核提供许多特定于设备和SOC的系统调用,让用户空间进程(包括应用)可以直接与内核进行交互            // 不过,其中许多系统调用Android未予使用或未予正式支持            // 通过seccomp,Android可使应用软件无法访问未使用的内核系统调用            // 由于应用无法访问这些系统调用,因此,它们不会被潜在的有害应用利用            // 该过滤器安装到zygote进程中,由于所有Android应用均衍生自该进程            // 因而会影响到所有应用            Seccomp.setPolicy();            ZygoteHooks.stopZygoteNoThreadCreation(); // 允许有其他线程了            if (startSystemServer) {                Runnable r = forkSystemServer(abiList, socketName, zygoteServer); // 启动SystemServer                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the                // child (system_server) process.                if (r != null) {                    r.run(); // 这里会调用到 RuntimeInit.java 中的 MethodAndArgsCaller 的 run方法,来正式进入 SystemServer的main函数                    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 {    Log.i(TAG, "zygoteServer.closeServerSocket finally finally");// 这个地方有两个调用的流程// 1: zygote 进程退出的时候会调用这个函数,用来关闭zygote自己创建的用来接收ActivityManager的链接请求的socket// 2:当每个子线程fork完毕,准备好之后,会走到这里,这个时候会在子进程中执行的,这里会调用closeServerSocket函数,确保从zygote集成过来的socket关闭。//    其实这个时候,因为子进程刚刚fock出来的时候就已经掉用过closeServerSocket函数了,因此再次调用,是没有效果的            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的对象,这个地方调用他的 run函数会进入到子进程的真正的main函数里面        }    }

这个main函数中,首选会创建一个ZygoteServer对象,这个就是用来处理后续zygote socket连接的地方。然后会解析前面传递进来的参数。根据参数决定是否启动SystemServer,启动SystemServer的部分,网上比较多,这里就不做详细介绍了。

  根据代码流程我们会发现,在main函数的最后会调用 caller = zygoteServer.runSelectLoop(abiList);进入到ZygoteServer类的runSelectLoop函数中。下面我们就着重分析下这个函数的具体实现。

 /**     * Runs the zygote process's select loop. Accepts new connections as     * they happen, and reads commands from connections one spawn-request's     * worth at a time.     */    Runnable runSelectLoop(String abiList) {// 记录需要监听的句柄        ArrayList fds = new ArrayList();// 记录上面监听的句柄所对应的处理类的实例对象        ArrayList peers = new ArrayList();        fds.add(mServerSocket.getFileDescriptor());        peers.add(null); // 这里add null 是为了使得它的index 和 fds 的index想对应。        while (true) {            StructPollfd[] pollFds = new StructPollfd[fds.size()];            for (int i = 0; i < pollFds.length; ++i) {                pollFds[i] = new StructPollfd();                pollFds[i].fd = fds.get(i);                pollFds[i].events = (short) POLLIN;            }            try {                Os.poll(pollFds, -1); // 开始进入监听模式 无论是监听到 连接请求还是 数据过来,这个函数都会返回            } catch (ErrnoException ex) {                throw new RuntimeException("poll failed", ex);            }            for (int i = pollFds.length - 1; i >= 0; --i) { // 根据监听到的消息长度,循环处理监听到的所有消息                if ((pollFds[i].revents & POLLIN) == 0) { // 无效消息,跳过                    continue;                }                Slog.e(TAG, "runSelectLoop i = "+i+" mIsForkChild = "+mIsForkChild);                if (i == 0) { // 如果 i是0,就说明监听到了连接请求,    // 此时调用 acceptCommandPeer 函数,这个函数会调用 mServerSocket.accept() 接受连接,并返回句柄// 然后用此句柄为参数创建了 ZygoteConnection 对象,然后由 ZygoteConnection 对象负责这一个连接的后续数据处理                    ZygoteConnection newPeer = acceptCommandPeer(abiList);                    peers.add(newPeer); // 添加到 peers 这个                    fds.add(newPeer.getFileDesciptor());  // 添加到 fds,然后在下次循环的时候,将刚刚接受的链接请求也一同添加到监听                } else { // 如果不是0.那就是上面 i=0的时候接受到的连接发来数据了。                    try {                        ZygoteConnection connection = peers.get(i); // 从刚刚记录的peers中获取处理对应数据的 ZygoteConnection 类                        final Runnable command = connection.processOneCommand(this);                        // 因为上面的 processOneCommand 函数调用中,如果创建了新的进程,上面的函数就会有两个返回,// 第一个是父进程的正常返回 此时的返回值是 null,还是在zygote进程中运行,并且mIsForkChild的值是没有变的,这个时候会进入到else中// 第二个返回时子进程的返回 此时的返回时不是空,此时是在子进程中运行,并且在子进程刚刚创建的时候,就将自己的mIsForkChild设置为 true了。                        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(i);                                fds.remove(i);                            }                        }                    } catch (Exception e) {                        if (!mIsForkChild) {                            // We're in the server so any exception here is one that has taken place                            // pre-fork while processing commands or reading / writing from the                            // control socket. Make a loud noise about any such exceptions so that                            // we know exactly what failed and why.                            Slog.e(TAG, "Exception executing zygote command: ", e);                            // Make sure the socket is closed so that the other end knows immediately                            // that something has gone wrong and doesn't time out waiting for a                            // response.                            ZygoteConnection conn = peers.remove(i);                            conn.closeSocket();                            fds.remove(i);                        } else {                            // We're in the child so any exception caught here has happened post                            // fork and before we execute ActivityThread.main (or any other main()                            // method). Log the details of the exception and bring down the process.                            Log.e(TAG, "Caught post-fork exception in child process.", e);                            throw e;                        }                    }                }            }        }    }


ArrayList fds = new ArrayList();
ArrayList peers = new ArrayList();
这个函数首先创建两个链表,第一个链表 fds 是用来保存要监听的socket文件描述符。
第二个链表peers用来保存对应的socket文件上的事件处理函数
另外 fds 和 peers 中元素是有对应关键的,即:fds中的第i个元素所对应的处理类就是peers中的第i个元素。这个后面的代码中可以看出来
fds.add(mServerSocket.getFileDescriptor());
peers.add(null);
这里将mServerSocket.getFileDescriptor()添加到fds里面,就是将zygote自己创建的用来监听ActivityManager连接的socket添加到fds链表里面。因为这个socket上没有对应的事件处理类,因此其对应的peers中的处理类对象设置为null

 

StructPollfd[] pollFds = new StructPollfd[fds.size()];for (int i = 0; i < pollFds.length; ++i) {// 填充pollFds    pollFds[i] = new StructPollfd();    pollFds[i].fd = fds.get(i);    pollFds[i].events = (short) POLLIN;}try {    Os.poll(pollFds, -1); // 开始进入监听模式 无论是监听到 连接请求还是 数据过来,这个函数都会返回} catch (ErrnoException ex) {    throw new RuntimeException("poll failed", ex);}

  上面这个部分代码就是每次循环都会 根据 fds 的大小重新建立pollFds,然后开始监听。

// 上面的函数一旦监听到动作就会返回,然后执行下面的代码for (int i = pollFds.length - 1; i >= 0; --i) { if ((pollFds[i].revents & POLLIN) == 0) {     continue; } // 上面根据监听的pollFds的长度,循环从后到前,依次判断是哪个句柄上存在数据,获取存在数据的句柄  if (i == 0) { // 如果i等于0,就说明是zygote的socket上监听到了连接请求。    // 对于新的链接请求,这里会调用 acceptCommandPeer 函数,这个函数会调用 mServerSocket.accept() 接受连接,并返回句柄    // 然后用此句柄为参数创建了 ZygoteConnection 对象,然后由 ZygoteConnection 对象负责这一个连接的后续数据处理    ZygoteConnection newPeer = acceptCommandPeer(abiList);    peers.add(newPeer); // 将新创建的ZygoteConnection添加到 peers 这个列表中    fds.add(newPeer.getFileDesciptor());  // 添加到 fds,然后在下次循环的时候,将刚刚接受的链接请求也一同添加到监听。 } else { // 如果i不是0.就说明是已将连接的socket上有数据发送过来了   ZygoteConnection connection = peers.get(i); // 从刚刚记录的peers中获取处理对应数据的 ZygoteConnection 类   final Runnable command = connection.processOneCommand(this); // 调用processOneCommand 函数处理socket发送过来的数据。   if (mIsForkChild) { // 由于前面processOneCommand函数很可能会创建新的进程,因此当再次返回这里的时候,有可能会有两个进程这里就需要判断是在那个进程中   // 这里是在子进程。表示在processOneCommand中fork了新的进程,此时返回来的时候,新的进程会设置 mIsForkChild 标志位       if (command == null) {           throw new IllegalStateException("command == null");       }       return command;   } else {      // 这里是在父进程中。表示的时候 zygote 进程,       // 下面会关闭socket,并且将此socket的文件句柄,以及对应的处理类从链表中移除。       if (connection.isClosedByPeer()) {           connection.closeSocket();           peers.remove(i);           fds.remove(i);       }   } }}

下面我们看下acceptCommandPeer函数的具体实现:

    /**     * Waits for and accepts a single command connection. Throws     * RuntimeException on failure.     // socket编程中,accept()调用主要用在基于连接的套接字类型,比如SOCK_STREAM和SOCK_SEQPACKET     // 它提取出所监听套接字的等待连接队列中第一个连接请求,创建一个新的套接字,并返回指向该套接字的文件描述符     // 新建立的套接字不在监听状态,原来所监听的套接字的状态也不受accept()调用的影响 // 从代码,可以看出 acceptCommandPeer 调用了server socket的accpet函数。于是当新的连接建立时, // zygote将会创建出一个新的socket与其通信,并将该socket加入到fds中。因此,一旦通信连接建立后,fds中将会包含有多个socket(我这里表述有点问题,这里实际上是同一个socket上面的不同的链接,请读者注意下)     */    private ZygoteConnection acceptCommandPeer(String abiList) {        try {// 注意这里的参数中调用了 mServerSocket.accept()            return createNewConnection(mServerSocket.accept(), abiList);        } catch (IOException ex) {            throw new RuntimeException(                    "IOException during accept()", ex);        }    }    protected ZygoteConnection createNewConnection(LocalSocket socket, String abiList)            throws IOException { // 这里根据参数,直接创建ZygoteConnection类对象        return new ZygoteConnection(socket, abiList);    }下面是ZygoteConnection的构造函数    /**     * Constructs instance from connected socket.     *     * @param socket non-null; connected socket     * @param abiList non-null; a list of ABIs this zygote supports.     * @throws IOException     */    ZygoteConnection(LocalSocket socket, String abiList) throws IOException {        mSocket = socket;        this.abiList = abiList;        mSocketOutStream= new DataOutputStream(socket.getOutputStream());        mSocketReader = new BufferedReader(new InputStreamReader(socket.getInputStream()), 256);        mSocket.setSoTimeout(CONNECTION_TIMEOUT_MILLIS);        try {            peer = mSocket.getPeerCredentials();        } catch (IOException ex) {            Log.e(TAG, "Cannot read peer credentials", ex);            throw ex;        }        isEof = false;    }

上面的代码流程很清晰,就是创建了一个ZygoteConnection对象。这个对象是用来处理这个socket具体发送过来的数据的。

下面我们在看下processOneCommand函数的具体实现。看看ZygoteConnection类中的processOneCommand函数都干了什么。

/** * Reads one start command from the command socket. If successful, a child is forked and a * {@code Runnable} that calls the childs main method (or equivalent) is returned in the child * process. {@code null} is always returned in the parent process (the zygote). * * If the client closes the socket, an {@code EOF} condition is set, which callers can test * for by calling {@code ZygoteConnection.isClosedByPeer}. */Runnable processOneCommand(ZygoteServer zygoteServer) {    String args[];    Arguments parsedArgs = null;    FileDescriptor[] descriptors;    try {        args = readArgumentList(); // 从socket 中读取传递过来的各种参数        descriptors = mSocket.getAncillaryFileDescriptors();    } catch (IOException ex) {        throw new IllegalStateException("IOException on command socket", ex);    }    // readArgumentList returns null only when it has reached EOF with no available    // data to read. This will only happen when the remote socket has disconnected.    if (args == null) {        isEof = true;        return null;    }    int pid = -1;    FileDescriptor childPipeFd = null;    FileDescriptor serverPipeFd = null;// parsedArgs 这个类是个工具类,主要是保存 并解析上面传递的参数,并保存解析的结果// 这里根据读取到的数据,来构建Arguments类,这个类会解析传递过来的数据,并保存解析的结果    parsedArgs = new Arguments(args);    if (parsedArgs.abiListQuery) { // 查询 AbiList        handleAbiListQuery();        return null;    }    if (parsedArgs.preloadDefault) { // 加载,并返回结果        handlePreload();        return null;    }    if (parsedArgs.preloadPackage != null) { // 预加载,        handlePreloadPackage(parsedArgs.preloadPackage, parsedArgs.preloadPackageLibs,                parsedArgs.preloadPackageCacheKey);        return null;    }    if (parsedArgs.permittedCapabilities != 0 || parsedArgs.effectiveCapabilities != 0) {        throw new ZygoteSecurityException("Client may not specify capabilities: " +                "permitted=0x" + Long.toHexString(parsedArgs.permittedCapabilities) +                ", effective=0x" + Long.toHexString(parsedArgs.effectiveCapabilities));    }// 安全检查    applyUidSecurityPolicy(parsedArgs, peer);    applyInvokeWithSecurityPolicy(parsedArgs, peer);    applyDebuggerSystemProperty(parsedArgs);    applyInvokeWithSystemProperty(parsedArgs);    int[] fdsToIgnore = null;Log.e(TAG, " processOneCommand  parsedArgs.invokeWith = "+parsedArgs.invokeWith);    if (parsedArgs.invokeWith != null) { // 这里好像一直都是空的,因此这里进不去        try {            FileDescriptor[] pipeFds = Os.pipe2(O_CLOEXEC); // 获取管道通讯的两端            childPipeFd = pipeFds[1];  // 写入端            serverPipeFd = pipeFds[0]; // 读取端            Os.fcntlInt(childPipeFd, F_SETFD, 0);            fdsToIgnore = new int[]{childPipeFd.getInt$(), serverPipeFd.getInt$()};        } catch (ErrnoException errnoEx) {            throw new IllegalStateException("Unable to set up pipe for invoke-with", errnoEx);        }    }    /**     * In order to avoid leaking descriptors to the Zygote child,     * the native code must close the two Zygote socket descriptors     * in the child process before it switches from Zygote-root to     * the UID and privileges of the application being launched.     *     * In order to avoid "bad file descriptor" errors when the     * two LocalSocket objects are closed, the Posix file     * descriptors are released via a dup2() call which closes     * the socket and substitutes an open descriptor to /dev/null.     */    int [] fdsToClose = { -1, -1 };    FileDescriptor fd = mSocket.getFileDescriptor();    if (fd != null) {        fdsToClose[0] = fd.getInt$();    }    fd = zygoteServer.getServerSocketFileDescriptor();    if (fd != null) {        fdsToClose[1] = fd.getInt$();    }    fd = null;// 创建子进程    pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,            parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,            parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,            parsedArgs.appDataDir);    try {        if (pid == 0) {            // in child // 因为子进程是复制于父进程,因此在子进程中 他的 mIsForkChild 值依然是父进程的原始值,false// 此时调用 setForkChild 只会设置子进程中的 mIsForkChild 变量的值,            zygoteServer.setForkChild(); //设置标志.这样在这个地方返回的时候,zygoteServer 就会走到子进程的处理函数中了            zygoteServer.closeServerSocket(); // 关闭子线程中的 socket,这个socket是从zygote集成过来的,因此这里需要首选关闭掉。            IoUtils.closeQuietly(serverPipeFd); // 关闭流            serverPipeFd = null;            return handleChildProc(parsedArgs, descriptors, childPipeFd);        } 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);            return null;        }    } finally {        IoUtils.closeQuietly(childPipeFd);        IoUtils.closeQuietly(serverPipeFd);    }}

这个函数的流程比较简单,首先读取对端发送过来的数据,然后根据发送过来的数据构建Arguments这个类,这类会解析传递过来的参数,并保存解析的结果。然后根据解析情况进行各种判断。然后调用Zygote.forkAndSpecialize创建新的进程,这个函数会有两次返回,第一次是在原来的父进程中返回,第二次是在新创建的子进程中返回。从这个函数返回起,子进程和父进程就分道扬镳了,这个时候,我们需要注意下自己看的这部分代码是在子线程中还是在父进程中。
 

下面我们在贴下forkAndSpecialize函数的代码 public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,       int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,       int[] fdsToIgnore, String instructionSet, String appDataDir) {     VM_HOOKS.preFork(); // 这里会等待zygote的所有子线程都退出即:停止Zyote的4个Daemon子线程的运行,初始化gc堆     // Resets nice priority for zygote process.     resetNicePriority(); // 设置zygote进程的优先级为 normal     int pid = nativeForkAndSpecialize(               uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,               fdsToIgnore, instructionSet, appDataDir);     // Enable tracing as soon as possible for the child process.     if (pid == 0) {// 子进程中         Trace.setTracingEnabled(true, debugFlags);         // Note that this event ends at the end of handleChildProc,         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");     }     VM_HOOKS.postForkCommon(); // 启动4个Deamon子线程     return pid; }

下面我们看下handleChildProc函数的大体流程

    private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,            FileDescriptor pipeFd) {        closeSocket(); // 关闭socket。这个socket 根前面刚刚关闭的socket不是同一个        if (parsedArgs.niceName != null) { // 设置子进程的名称            Process.setArgV0(parsedArgs.niceName);        }        // End of the postFork event.        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);        if (parsedArgs.invokeWith != null) { // 这里好像一直都是空的            WrapperInit.execApplication(parsedArgs.invokeWith,                    parsedArgs.niceName, parsedArgs.targetSdkVersion,                    VMRuntime.getCurrentInstructionSet(),                    pipeFd, parsedArgs.remainingArgs);            // Should not get here.            throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");        } else { // 这里调用 ZygoteInit.zygoteInit 进一步初始化            return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,                    null /* classLoader */);        }    }

下面我们看下ZygoteInit.zygoteInit的实现

// 这个函数是一个公共的函数,启动 systemServer 以及启动 应用都会调用到这里    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(); // 将system.out 以及System.err 的输出重定向到 Android  log中        RuntimeInit.commonInit();        ZygoteInit.nativeZygoteInit(); // 初始化native层        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);    }    下面是applicationInit函数的实现    protected static Runnable applicationInit(int targetSdkVersion, String[] argv,            ClassLoader classLoader) {// 如果应用调用System.exit()直接终结一个进程,但是没有调用 shutdown hooks,这个对于一个Android应用了来说确实可以// 但是shutdown hooks是用来关闭Binder的,如果没有调用,会导致一些线程遗留,造成crash        nativeSetExitWithoutCleanup(true);        // We want to be fairly aggressive about heap utilization, to avoid        // holding on to a lot of memory that isn't needed.        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);  // 与内存占用相关        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion); // 设置sdk版本        final Arguments args = new Arguments(argv);        // The end of of the RuntimeInit event (see #zygoteInit).        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);        // Remaining arguments are passed to the start class's static main        return findStaticMain(args.startClass, args.startArgs, classLoader);    }

 这个findStaticMain函数会根据传递的参数,找到对应的java类的静态main函数,然后 通过return new MethodAndArgsCaller(m, argv);来返回一个MethodAndArgsCaller类,下面我们看下MethodAndArgsCaller类的实现。

  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 }); //这个会调用相应的方法并将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,那么这里就会调用SystemServer.java的main函数,如果是启动的应用,那就会调用ActivityThread.java 的main函数。

但是上面的findStaticMain并没有调用这个run函数,而是仅仅创建了一个类对象,然后就将这个对象返回了。那么这个函数是在哪里调用的呢,这里就一层一层的返回了,首先这里会返回到ZygoteConnection.java的processOneCommand 函数,然后这个函数接着返回,会返回到ZygoteServer.java中的runSelectLoop函数中,在这个函数有下面的代码:

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; // 这里再次返回
}

上面的代码会继续返回到ZygoteInit.java中的main函数中;下面这部分代码就会main函数的处理函数。

            // 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 {    Log.i(TAG, "zygoteServer.closeServerSocket finally finally");// 这个地方有两个调用的流程// 1: zygote 进程退出的时候会调用这个函数,用来关闭zygote自己创建的用来接收ActivityManager的链接请求的socket// 2:当每个子线程fork完毕,准备好之后,会走到这里,这个时候会在子进程中执行的,这里会调用closeServerSocket函数,确保从zygote集成过来的socket关闭。//    其实这个时候,因为子进程刚刚fock出来的时候就已经掉用过closeServerSocket函数了,因此再次调用,是没有效果的            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的对象,这个地方调用他的 run函数会进入到子进程的真正的main函数里面        }

上面的这段代码,当zygoteServer.runSelectLoop返回的时候,就已经是在子进程中了,此时会在后面调用caller.run();来执行对应的java文件的main函数。至此zygote中启动新进程的流程就梳理完成了。

 

更多相关文章

  1. C语言函数以及函数的使用
  2. android杀进程方法
  3. Android:WebView与Javascript交互(相互调用参数、传值)
  4. 利用oom_adj提高Application所在进程的优先级
  5. Android Hook学习之ptrace函数的使用
  6. Android SDKVersion 参数列表
  7. android中线程进程模型
  8. Android之布局参数
  9. Android ContentProvider 多进程multiprocess 详解

随机推荐

  1. 细读《深入理解 Android(安卓)内核设计思
  2. Android之系统架构
  3. android如何使webview不跳到自带的浏览器
  4. 基于android ndk-r15 生成ffmpeg4.0 .so
  5. Android环境的搭建
  6. Android之异步任务AsyncTask解析XML数据
  7. 二维码扫描(横屏、竖屏、解决竖屏后拉伸问
  8. Android-抽象类抽象方法
  9. 搭建NDK环境,运行samples
  10. android--------自定义控件 之 方法篇