跳转至

Zygote 孵化流程

1. System Server 请求 fork

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
// zygote 启动时请求的 forkSystemServer 方法 line 685:692
    /**
     * Prepare the arguments and forks for the system server process.
     *
     * @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) {
// 配置 fork 相关参数 line 718:730

        /* Hardcoded command line to start the system server */
        String[] args = {
                "--setuid=1000",
                "--setgid=1000",
                "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
                        + "1024,1032,1065,3001,3002,3003,3005,3006,3007,3009,3010,3011,3012",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                "com.android.server.SystemServer",
        };
// 调用 Zygote.forkSystemServer 方法 line 776:799

            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    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) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

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

        return null;

2. Zygote 监听处理其他进程的 fork 请求

当别的应用需要孵化一个新的进程时,会通过本地套字节(socket)向 Zygote 发送请求,Zygote 收到请求后会执行 fork 来创建新的进程。

具体代码处理流程如下:

  1. ZygoteServer 监听请求
    上文提到 ZygoteInit 启动了 runSelectLoop 方法负责监听和管理请求,代码中可以看出将具体的处理工作交给 ZygoteConnection

    /frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
    // runSelectLoop 方法 line 388:394
        /**
         * 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.
         * @param abiList list of ABIs supported by this zygote.
         */
        Runnable runSelectLoop(String abiList) {
    // runSelectLoop 方法 line 508:521
                        if (pollIndex == 0) {
                            // Zygote server socket
                            ZygoteConnection newPeer = acceptCommandPeer(abiList);
                            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);
                                boolean multipleForksOK = !isUsapPoolEnabled()
                                        && ZygoteHooks.isIndefiniteThreadSuspensionSafe();
                                final Runnable command =
                                        connection.processCommand(this, multipleForksOK);
    

  2. ZygoteConnection 处理连接
    ZygoteConnection 负责解析请求参数,并调用 Zygote.forkAndSpecialize 来执行 fork 操作。

    /frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
    // 可以看到调用 Native 层的 fork 逻辑 line 248:276
                        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.mIsTopApp, parsedArgs.mPkgDataInfoList,
                                parsedArgs.mAllowlistedDataInfoList, parsedArgs.mBindMountAppDataDirs,
                                parsedArgs.mBindMountAppStorageDirs,
                                parsedArgs.mBindMountSyspropOverrides);
    
                        try {
                            if (pid == 0) {
                                // in child
                                zygoteServer.setForkChild();
    
                                zygoteServer.closeServerSocket();
                                IoUtils.closeQuietly(serverPipeFd);
                                serverPipeFd = null;
    
                                return handleChildProc(parsedArgs, 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, serverPipeFd);
                                return null;
                            }
    

  3. Zygote 执行 Fork
    forkAndSpecialize 方法会调用 native 方法 nativeForkAndSpecialize 来真正执行 fork

    我们可以对比一下孵化普通应用进程 (forkAndSpecialize) 和孵化 SystemServer (forkSystemServer) 的代码,它们最终都依赖 native 方法。

    /frameworks/base/core/java/com/android/internal/os/Zygote.java
    // line 368:403
        static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
                int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
                int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
                boolean isTopApp, String[] pkgDataInfoList, String[] allowlistedDataInfoList,
                boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs,
                boolean bindMountSyspropOverrides) {
            ZygoteHooks.preFork();
    
            int pid = nativeForkAndSpecialize(
                    uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                    fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp,
                    pkgDataInfoList, allowlistedDataInfoList, bindMountAppDataDirs,
                    bindMountAppStorageDirs, bindMountSyspropOverrides);
            if (pid == 0) {
                // Note that this event ends at the end of handleChildProc,
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
    
                // If no GIDs were specified, don't make any permissions changes based on groups.
                if (gids != null && gids.length > 0) {
                    NetworkUtilsInternal.setAllowNetworkingForProcess(containsInetGid(gids));
                }
            }
    
            // Set the Java Language thread priority to the default value for new apps.
            Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
    
            ZygoteHooks.postForkCommon();
            return pid;
        }
    
        private static native int nativeForkAndSpecialize(int uid, int gid, int[] gids,
                int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
                int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet,
                String appDataDir, boolean isTopApp, String[] pkgDataInfoList,
                String[] allowlistedDataInfoList, boolean bindMountAppDataDirs,
                boolean bindMountAppStorageDirs, boolean bindMountSyspropOverrides);
    
    /frameworks/base/core/java/com/android/internal/os/Zygote.java
    // line 501:517
        static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
                int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
            ZygoteHooks.preFork();
    
            int pid = nativeForkSystemServer(
                    uid, gid, gids, runtimeFlags, rlimits,
                    permittedCapabilities, effectiveCapabilities);
    
            // Set the Java Language thread priority to the default value for new apps.
            Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
    
            ZygoteHooks.postForkCommon();
            return pid;
        }
    
        private static native int nativeForkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
                int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
    

3. Native 层:执行 Fork

Java 层的 native 方法最终会调用到 C++ 层的 ForkCommon 函数来完成进程的创建。

/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
// line 2530:2585
static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
        JNIEnv* env, jclass, jint uid, jint gid, jintArray gids, jint runtime_flags,
        jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name,
        jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote,
        jstring instruction_set, jstring app_data_dir, jboolean is_top_app,
        jobjectArray pkg_data_info_list, jobjectArray allowlisted_data_info_list,
        jboolean mount_data_dirs, jboolean mount_storage_dirs, jboolean mount_sysprop_overrides) {
    jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
    jlong bounding_capabilities = CalculateBoundingCapabilities(env, uid, gid, gids);

    if (UNLIKELY(managed_fds_to_close == nullptr)) {
      zygote::ZygoteFailure(env, "zygote", nice_name,
                            "Zygote received a null fds_to_close vector.");
    }

    std::vector<int> fds_to_close =
        ExtractJIntArray(env, "zygote", nice_name, managed_fds_to_close).value();
    std::vector<int> fds_to_ignore =
        ExtractJIntArray(env, "zygote", nice_name, managed_fds_to_ignore)
            .value_or(std::vector<int>());

    std::vector<int> usap_pipes = MakeUsapPipeReadFDVector();

    fds_to_close.insert(fds_to_close.end(), usap_pipes.begin(), usap_pipes.end());
    fds_to_ignore.insert(fds_to_ignore.end(), usap_pipes.begin(), usap_pipes.end());

    fds_to_close.push_back(gUsapPoolSocketFD);

    if (gUsapPoolEventFD != -1) {
      fds_to_close.push_back(gUsapPoolEventFD);
      fds_to_ignore.push_back(gUsapPoolEventFD);
    }

    if (gSystemServerSocketFd != -1) {
        fds_to_close.push_back(gSystemServerSocketFd);
        fds_to_ignore.push_back(gSystemServerSocketFd);
    }

    if (gPreloadFds && gPreloadFdsExtracted) {
        fds_to_ignore.insert(fds_to_ignore.end(), gPreloadFds->begin(), gPreloadFds->end());
    }

    pid_t pid = zygote::ForkCommon(env, /* is_system_server= */ false, fds_to_close, fds_to_ignore,
                                   true);

    if (pid == 0) {
        SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities,
                         bounding_capabilities, mount_external, se_info, nice_name, false,
                         is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
                         is_top_app == JNI_TRUE, pkg_data_info_list, allowlisted_data_info_list,
                         mount_data_dirs == JNI_TRUE, mount_storage_dirs == JNI_TRUE,
                         mount_sysprop_overrides == JNI_TRUE);
    }
    return pid;
}
/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
// line 2587:2643
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) {
  ATRACE_CALL();
  std::vector<int> fds_to_close(MakeUsapPipeReadFDVector()),
                   fds_to_ignore(fds_to_close);

  fds_to_close.push_back(gUsapPoolSocketFD);

  if (gUsapPoolEventFD != -1) {
    fds_to_close.push_back(gUsapPoolEventFD);
    fds_to_ignore.push_back(gUsapPoolEventFD);
  }

  if (gSystemServerSocketFd != -1) {
      fds_to_close.push_back(gSystemServerSocketFd);
      fds_to_ignore.push_back(gSystemServerSocketFd);
  }

  pid_t pid = zygote::ForkCommon(env, true,
                                 fds_to_close,
                                 fds_to_ignore,
                                 true);
  if (pid == 0) {
      // System server prcoess does not need data isolation so no need to
      // know pkg_data_info_list.
      SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, permitted_capabilities,
                       effective_capabilities, 0, MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
                       false, nullptr, nullptr, /* is_top_app= */ false,
                       /* pkg_data_info_list */ nullptr,
                       /* allowlisted_data_info_list */ nullptr, false, false, false);
  } else if (pid > 0) {
      // The zygote process checks whether the child process has died or not.
      ALOGI("System server process %d has been created", pid);
      gSystemServerPid = pid;
      // There is a slight window that the system server process has crashed
      // but it went unnoticed because we haven't published its pid yet. So
      // we recheck here just to make sure that all is well.
      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!");
      }

      if (UsePerAppMemcg()) {
          // Assign system_server to the correct memory cgroup.
          // Not all devices mount memcg so check if it is mounted first
          // to avoid unnecessarily printing errors and denials in the logs.
          if (!SetTaskProfiles(pid, std::vector<std::string>{"SystemMemoryProcess"})) {
              ALOGE("couldn't add process %d into system memcg group", pid);
          }
      }
  }
  return pid;
}

可以看到,它们都调用了 ForkCommon 方法。

我们来看 ForkCommon 的实现方法:

/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
// line 2421:2523
// Utility routine to fork a process from the zygote.
NO_STACK_PROTECTOR
pid_t zygote::ForkCommon(JNIEnv* env, bool is_system_server,
                         const std::vector<int>& fds_to_close,
                         const std::vector<int>& fds_to_ignore,
                         bool is_priority_fork,
                         bool purge) {
//...
  pid_t pid = fork();

  if (pid == 0) {
    if (is_priority_fork) {
      setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX);
    } else {
      setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MIN);
    }
//...
  return pid;
}

ForkCommon 调用了底层的 fork() 方法,并且接受了返回的 pid。