“ 进程创建 ” 的原理


# 核心源码

关键类 路径
runtime.cc art/runtime/runtime.cc
dalvik_system_ZygoteHooks.cc art/runtime/native/dalvik_system_ZygoteHooks.cc
fork.cpp bionic/libc/bionic/fork.cpp
app_main.java frameworks/base/cmds/app_process/app_main.cpp
AndroidRuntime.cpp frameworks/base/core/jni/AndroidRuntime.cpp
com_android_internal_os_Zygote.cpp frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
Daemons.java libcore/libart/src/main/java/java/lang/Daemons.java
ZygoteHooks.java libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
ActivityThread.java frameworks/base/core/java/android/app/ActivityThread.java
Process.java frameworks/base/core/java/android/os/Process.java
ZygoteProcess.java frameworks/base/core/java/android/os/ZygoteProcess.java
RuntimeInit.java frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
Zygote.java frameworks/base/core/java/com/android/internal/os/Zygote.java
ZygoteInit.java frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
ZygoteServer.java frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
ZygoteConnection.java frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java


# 进程和线程

✎  进程:每个 App 在启动前必须先创建一个进程,该进程是由 Zygote fork 出来的,进程具有独立的资源空间,用于承载 App 上运行的各种 Activity / Service 等组件。进程对于上层应用来说是完全透明的,这也是 google 有意为之,让 App 程序都是运行在 Android Runtime。大多数情况一个 App 就运行在一个进程中,除非在 AndroidManifest.xml 中配置 Android:process 属性,或通过 native 代码 fork 进程。

✎  线程:线程对应用开发者来说非常熟悉,比如每次 new Thread().start() 都会创建一个新的线程,该线程并没有自己独立的地址空间,而是与其所在进程之间资源共享。从 Linux 角度来说进程与线程都是一个 task_struct 结构体,除了是否共享资源外,并没有其他本质的区别。


# 进程创建流程

进程创建流程.png


接下来,我们就挖掘源码、深入探讨进程是如何造出来的!在 【 Android 10 四大组件 】系列 – Activity 的 “ 启动流程 “ 一文中,我们探讨过 Activity 启动最终会调用 Process.Start() 创建进程,如果不清楚相关流程,可以先看下这篇文章。


一、system_server

首先探讨 system_server 发起请求的源码流程:

1.1 Process.start()

// frameworks/base/core/java/android/os/Process.java

/**
 * Tools for managing OS processes.
 */
public class Process {

    public static final ZygoteProcess ZYGOTE_PROCESS = new ZygoteProcess();

    public static ProcessStartResult start(@NonNull final String processClass,
                                           @Nullable final String niceName,
                                           int uid, int gid, @Nullable int[] gids,
                                           ... ...

                                           @Nullable long[] disabledCompatChanges,
                                           @Nullable String[] zygoteArgs) {
        return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, packageName,
                    zygotePolicyFlags, isTopApp, disabledCompatChanges, zygoteArgs);
    }

}

1.2 ZygoteProcess.start()

// frameworks/base/core/java/android/os/ZygoteProcess.java

public class ZygoteProcess {

    public final Process.ProcessStartResult start(@NonNull final String processClass,
                                                  final String niceName,
                                                  ... ...

                                                  @Nullable long[] disabledCompatChanges,
                                                  @Nullable String[] zygoteArgs) {
        if (fetchUsapPoolEnabledPropWithMinInterval()) {
            informZygotesOfUsapPoolStatus();
        }

        try {
            // 调用 startViaZygote() 方法
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
                    packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges, zygoteArgs);
        } catch (ZygoteStartFailedEx ex) {
            Log.e(LOG_TAG,
                    "Starting VM process through Zygote failed");
            throw new RuntimeException(
                    "Starting VM process through Zygote failed", ex);
        }
    }

}

1.3 ZygoteProcess.startViaZygote()

// frameworks/base/core/java/android/os/ZygoteProcess.java

public class ZygoteProcess {

    private Process.ProcessStartResult startViaZygote(@NonNull final String processClass,
                                                      @Nullable final String niceName,
                                                      final int uid, final int gid,
                                                      ... ...

                                                      @Nullable long[] disabledCompatChanges,
                                                      @Nullable String[] extraArgs)
                                                      throws ZygoteStartFailedEx {
        // 生成 argsForZygote 数组,该数组保存了进程的 uid、gid、groups、target-sdk 等一系列的参数
        ArrayList<String> argsForZygote = new ArrayList<String>();

        argsForZygote.add("--runtime-args");
        argsForZygote.add("--setuid=" + uid);
        argsForZygote.add("--setgid=" + gid);
        argsForZygote.add("--runtime-flags=" + runtimeFlags);
        ... ...

        argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
        ... ...

        synchronized(mLock) {
            // 方法 1:openZygoteSocketIfNeeded()
            // 方法 2:zygoteSendArgsAndGetResult()
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
                                              zygotePolicyFlags,
                                              argsForZygote);
        }
    }

}

1.4 ZygoteProcess.openZygoteSocketIfNeeded()

从方法名,我们大概就已经清楚这个方法是干什么的了。

// frameworks/base/core/java/android/os/ZygoteProcess.java

public class ZygoteProcess {

    private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
        try {
            attemptConnectionToPrimaryZygote();    // 向主 Zygote 发起连接操作

            if (primaryZygoteState.matches(abi)) {
                return primaryZygoteState;
            }

            if (mZygoteSecondarySocketAddress != null) {
                // The primary zygote didn't match. Try the secondary.
                attemptConnectionToSecondaryZygote();    // 向第二个 Zygote 发起连接操作

                if (secondaryZygoteState.matches(abi)) {
                    return secondaryZygoteState;
                }
            }
        } catch (IOException ioe) {
            throw new ZygoteStartFailedEx("Error connecting to zygote", ioe);
        }

        throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
    }

    private void attemptConnectionToPrimaryZygote() throws IOException {
        if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
            // 向主 zygote 发起 connect() 操作
            primaryZygoteState =
                    ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress);

            maybeSetApiBlacklistExemptions(primaryZygoteState, false);
            maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
            maybeSetHiddenApiAccessStatslogSampleRate(primaryZygoteState);
        }
    }

    private void attemptConnectionToSecondaryZygote() throws IOException {
        if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
            // 当主 zygote 没能匹配成功,则采用第二个 zygote,发起 connect() 操作
            secondaryZygoteState =
                    ZygoteState.connect(mZygoteSecondarySocketAddress,
                            mUsapPoolSecondarySocketAddress);

            maybeSetApiBlacklistExemptions(secondaryZygoteState, false);
            maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState);
            maybeSetHiddenApiAccessStatslogSampleRate(secondaryZygoteState);
        }
    }

}

openZygoteSocketIfNeeded(abi) 方法是根据当前的 abi 来选择与 zygote 还是 zygote64 来进行通信。

1.5 ZygoteProcess.zygoteSendArgsAndGetResult()

// frameworks/base/core/java/android/os/ZygoteProcess.java

public class ZygoteProcess {

    @GuardedBy("mLock")
    private Process.ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, int zygotePolicyFlags, @NonNull ArrayList<String> args)
            throws ZygoteStartFailedEx {
        ... ...

        return attemptZygoteSendArgsAndGetResult(zygoteState, msgStr);    
    }

    private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(
            ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {
        try {
            final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
            final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;

            zygoteWriter.write(msgStr);
            zygoteWriter.flush();

            Process.ProcessStartResult result = new Process.ProcessStartResult();
            // 等待 socket 服务端(即 zygote)返回新创建的进程 pid;
            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);
        }        
    }

}

这个方法的定义就说明了它的含义,主要功能是通过 socket 通道向 Zygote 进程发送一个 “参数列表”,然后进入 “阻塞等待” 状态,直到远端的 socket 服务端 发送回来新创建的进程 pid 才返回。

既然 system_server 进程的 zygoteSendArgsAndGetResult() 方法通过 socketZygote 进程发送消息,这时便会唤醒 Zygote 进程,来响应 socket 客户端的请求(即 system_server 端),接下来的操作便是在 Zygote 来创建进程。

1.6 源码流程图(system_server)

源码流程图.png


二、Zygote

Zygote 进程是由 init 进程创建的,进程启动之后便会调用 ZygoteInit.main() 方法,经过创建 socket 管道,预加载资源后,调用 runSelectLoop()方法。

2.1 Zygote.main()

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

public class ZygoteInit {

    public static void main(String argv[]) {
        ZygoteServer zygoteServer = null;
        ... ...

        try {
            ... ...

            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();
         }
    }

}

2.2 ZygoteServer.runSelectLoop()

// frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

class ZygoteServer {

    Runnable runSelectLoop(String abiList) {
        ArrayList<FileDescriptor> socketFDs = new ArrayList<>();
        ArrayList<ZygoteConnection> peers = new ArrayList<>();

        // mZygoteSocket 是 socket 通信中的服务端,即 zygote 进程,保存到 fds[0]
        socketFDs.add(mZygoteSocket.getFileDescriptor());
        peers.add(null);

        mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;

        while (true) {
            fetchUsapPoolPolicyPropsWithMinInterval();
            mUsapPoolRefillAction = UsapPoolRefillAction.NONE;

            int[] usapPipeFDs = null;
            StructPollfd[] pollFDs;

            // Allocate enough space for the poll structs, taking into account
            // the state of the USAP pool for this Zygote (could be a
            // regular Zygote, a WebView Zygote, or an AppZygote).
            if (mUsapPoolEnabled) {
                usapPipeFDs = Zygote.getUsapPipeFDs();
                pollFDs = new StructPollfd[socketFDs.size() + 1 + usapPipeFDs.length];
            } else {
                pollFDs = new StructPollfd[socketFDs.size()];
            }
            ... ...

            int pollReturnValue;
            try {
                // 处理轮询状态,当 pollFDs 有事件到来则往下执行,否则阻塞在这里
                pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }

            if (pollReturnValue == 0) {
                mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
                mUsapPoolRefillAction = UsapPoolRefillAction.DELAYED;

            } else {
                boolean usapPoolFDRead = false;

                while (--pollIndex >= 0) {
                    // 采用 I/O 多路复用机制,当接收到客户端发出连接请求或者数据处理请求到来,则往下执行;
                    // 否则进入 continue,跳出本次循环。
                    if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
                        continue;
                    }

                    if (pollIndex == 0) {
                        // Zygote server socket
                        // 即 fds[0],代表的是 mServerSocket,则意味着有客户端连接请求;
                        // 创建 ZygoteConnection 对象,并添加到 fds。
                        ZygoteConnection newPeer = acceptCommandPeer(abiList);
                        peers.add(newPeer);
                        socketFDs.add(newPeer.getFileDescriptor());

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

                        try {
                            // pollIndex > 0,则代表通过 socket 接收来自对端的数据,并执行相应操作
                            ZygoteConnection connection = peers.get(pollIndex);
                            final Runnable command = connection.processOneCommand(this);
                            ... ...

                        } catch (Exception e) {

                        } finally {
                            mIsForkChild = false;
                        }

                    } else {
                        ... ...
                    }
                }

            }
            ... ...

        }
    }

}

2.3 ZygoteServer.acceptCommandPeer()

// frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

class ZygoteServer {

    /**
     * Waits for and accepts a single command connection. Throws
     * RuntimeException on failure.
     */
    private ZygoteConnection acceptCommandPeer(String abiList) {
        try {
            // 接收客户端发送过来的 connect() 操作,Zygote 作为服务端执行 accept() 操作
            return createNewConnection(mZygoteSocket.accept(), abiList);
        } catch (IOException ex) {
            throw new RuntimeException(
                    "IOException during accept()", ex);
        }
    }

}

没有连接请求时会进入休眠状态,当有创建新进程的连接请求时,唤醒 Zygote 进程,创建 Socket 通道 ZygoteConnection,然后执行 ZygoteConnection 的 processOneCommand() 方法。

2.4 ZygoteConnection.processOneCommand()

// frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

class ZygoteConnection {

    Runnable processOneCommand(ZygoteServer zygoteServer) {
        String[] args;

        try {
            args = Zygote.readArgumentList(mSocketReader);
        } 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;
        FileDescriptor childPipeFd = null;
        FileDescriptor serverPipeFd = null;

        // 将 binder 客户端传递过来的参数,解析成 Arguments 对象格式
        ZygoteArguments parsedArgs = new ZygoteArguments(args);
        ... ...

        int [] fdsToClose = { -1, -1 };

        FileDescriptor fd = mSocket.getFileDescriptor();

        if (fd != null) {
            fdsToClose[0] = fd.getInt$();
        }

        fd = zygoteServer.getZygoteSocketFileDescriptor();

        if (fd != null) {
            fdsToClose[1] = fd.getInt$();
        }

        // forkAndSpecialize() 为重点方法
        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);

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

                zygoteServer.closeServerSocket();
                IoUtils.closeQuietly(serverPipeFd);    // 子进程执行
                serverPipeFd = null;

                // App 进程创建完成后(fork 成功后),会执行此方法
                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;
            }
        } finally {
            IoUtils.closeQuietly(childPipeFd);
            IoUtils.closeQuietly(serverPipeFd);
        }
    }

}

2.5 Zygote.forkAndSpecialize()

// frameworks/base/core/java/com/android/internal/os/Zygote.java

public final class Zygote {

    public 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) {
        ZygoteHooks.preFork();

        // 重点方法
        int pid = nativeForkAndSpecialize(
                uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp);
        if (pid == 0) {
            // Note that this event ends at the end of handleChildProc,
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
        }

        // Set the Java Language thread priority to the default value for new apps.
        Thread.currentThread().setPriority(Thread.NORM_PRIORITY);

        ZygoteHooks.postForkCommon();
        return pid;
    }

}

2.6 ZygoteHooks.preFork()

// libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java

public final class ZygoteHooks {

    public static void preFork() {
        Daemons.stop();                  // 停止 4 个 Daemon 子线程
        token = nativePreFork();         // 等待所有子线程结束
        waitUntilAllThreadsStopped();    // 完成 gc 堆的初始化工作
    }

}

2.6.1 Daemons.stop()

// libcore/libart/src/main/java/java/lang/Daemons.java

public final class Daemons {

    private static final Daemon[] DAEMONS = new Daemon[] {
            HeapTaskDaemon.INSTANCE,           // Java 堆整理线程
            ReferenceQueueDaemon.INSTANCE,     // 引用队列线程
            FinalizerDaemon.INSTANCE,          // 析构线程
            FinalizerWatchdogDaemon.INSTANCE,  // 析构监控线程
    };

    @UnsupportedAppUsage
    public static void stop() {
        for (Daemon daemon : DAEMONS) {
            daemon.stop();
        }
    }

}

2.6.2 ZygoteHooks.nativePreFork()

// libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java

public final class ZygoteHooks {

    private static native long nativePreFork();

}

// art/runtime/native/dalvik_system_ZygoteHooks.cc

static jlong ZygoteHooks_nativePreFork(JNIEnv* env, jclass) {
  Runtime* runtime = Runtime::Current();
  CHECK(runtime->IsZygote()) << "runtime instance not started with -Xzygote";

  runtime->PreZygoteFork();    // 执行 PreZygoteFork 函数

  // Grab thread before fork potentially makes Thread::pthread_key_self_ unusable.
  // 将线程转换为 long 型并保存到 token,该过程是非安全的
  return reinterpret_cast<jlong>(ThreadForEnv(env));
}

// art/runtime/runtime.cc

void Runtime::PreZygoteFork() {
  if (GetJit() != nullptr) {
    GetJit()->PreZygoteFork();
  }
  heap_->PreZygoteFork();    // 堆的初始化工作,这里就不继续再往下追 art 虚拟机了
  PreZygoteForkNativeBridge();
}

2.6.3 ZygoteHooks.waitUntilAllThreadsStopped()

// libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java

public final class ZygoteHooks {

    private static void waitUntilAllThreadsStopped() {
        File tasks = new File("/proc/self/task");
        // All Java daemons are stopped already. We're just waiting for their OS counterparts to
        // finish as well. This shouldn't take much time so spinning is ok here.
        // 当 /proc 中线程数大于 1,就出让 CPU 直到只有一个线程,才退出循环
        while (tasks.list().length > 1) {
          Thread.yield();
        }
    }

}

2.7 Zygote.nativeForkAndSpecialize()

接下来,我们跟踪 nativeForkAndSpecialize 的源码:

// frameworks/base/core/java/com/android/internal/os/Zygote.java

public final class Zygote {

    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);

}

// frameworks/base/core/jni/com_android_internal_os_Zygote.cpp

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) {
    ... ...

    pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore, true);

    if (pid == 0) {
      SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
                       capabilities, capabilities,
                       mount_external, se_info, nice_name, false,
                       is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
                       is_top_app == JNI_TRUE);
    }
    return pid;
}

2.8 com_android_internal_os_Zygote.ForkCommon()

// frameworks/base/core/jni/com_android_internal_os_Zygote.cpp

// Utility routine to fork a process from the zygote.
static pid_t 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) {
    // 设置子进程的 signal 信号处理函数
    SetSignalHandlers();
    ... ...

    // fork 子线程
    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);
        }

        // The child process.
        PreApplicationInit();

        // 关闭并清除文件描述符
        DetachDescriptors(env, fds_to_close, fail_fn);

        // Invalidate the entries in the USAP table.
        ClearUsapTable();

        // Re-open all remaining open file descriptors so that they aren't shared
        // with the zygote across a fork.
        gOpenFdTable->ReopenOrDetach(fail_fn);

        // Turn fdsan back on.
        android_fdsan_set_error_level(fdsan_error_level);

        // Reset the fd to the unsolicited zygote socket
        gSystemServerSocketFd = -1;
    } else {
        ALOGD("Forked child process %d", pid);
    }

    // We blocked SIGCHLD prior to a fork, we unblock it here.
    UnblockSignal(SIGCHLD, fail_fn);

    return pid;
}

2.9 com_android_internal_os_Zygote.SpecializeCommon()

// frameworks/base/core/jni/com_android_internal_os_Zygote.cpp

// Utility routine to specialize a zygote child process.
static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
                             jint runtime_flags, jobjectArray rlimits,
                             jlong permitted_capabilities, jlong effective_capabilities,
                             jint mount_external, jstring managed_se_info,
                             jstring managed_nice_name, bool is_system_server,
                             bool is_child_zygote, jstring managed_instruction_set,
                             jstring managed_app_data_dir, bool is_top_app) {
    ... ...

    // 对于非 system_server 子进程,则创建进程组
    if (!is_system_server && getuid() == 0) {
        const int rc = createProcessGroup(uid, getpid());
        if (rc == -EROFS) {
            ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?");
        } else if (rc != 0) {
            ALOGE("createProcessGroup(%d, %d) failed: %s", uid, /* pid= */ 0, strerror(-rc));
        }
    }

    SetGids(env, gids, fail_fn);    // 设置 group
    SetRLimits(env, rlimits, fail_fn);    // 设置资源 limit
    ... ...

    if (setresgid(gid, gid, gid) == -1) {
        fail_fn(CREATE_ERROR("setresgid(%d) failed: %s", gid, strerror(errno)));
    }

    SetSchedulerPolicy(fail_fn, is_top_app);    // 设置调度策略

    if (setresuid(uid, uid, uid) == -1) {
        fail_fn(CREATE_ERROR("setresuid(%d) failed: %s", uid, strerror(errno)));
    }
    ... ...

    SetCapabilities(permitted_capabilities, effective_capabilities, permitted_capabilities, fail_fn);

    // selinux 上下文
    if (selinux_android_setcontext(uid, is_system_server, se_info_ptr, nice_name_ptr) == -1) {
        fail_fn(CREATE_ERROR("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed",
                           uid, is_system_server, se_info_ptr, nice_name_ptr));
    }
    ... ...

    // 在 Zygote 子进程中,设置信号 SIGCHLD 的处理器恢复为默认行为
    UnsetChldSignalHandler();

    // 等价于调用 zygote.callPostForkChildHooks()
    env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
                            is_system_server, is_child_zygote, managed_instruction_set);
    ... ...

}

2.9 源码流程图(system_server)

函数调用关系流程图.png

2.10 fork()

fork() 采用 copy on write 技术,这是 linux 创建进程的标准方法,调用一次,返回两次,返回值有 3 种类型。

        ✎  父进程中,fork 返回新创建的子进程的 pid;
        ✎  子进程中,fork 返回 0;
        ✎  当出现错误时,fork 返回负数。(当进程数超过上限或者系统内存不足时会出错)

fork() 的主要工作是寻找空闲的进程号 pid,然后从父进程拷贝进程信息,例如数据段和代码段、fork() 后子进程要执行的代码等。

Zygote 进程是所有 Android 进程的母体,包括 system_server 和各个 App 进程。zygote 利用 fork() 方法生成新进程,对于新进程 A 复用 Zygote 进程本身的资源,再加上新进程 A 相关的资源,构成新的应用进程 A。

我们来看看源码:

// bionic/libc/bionic/fork.cpp

int fork() {
    __bionic_atfork_run_prepare();

    pthread_internal_t* self = __get_thread();

    int result = clone(nullptr,
                       nullptr,
                       (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD),
                       nullptr,
                       nullptr,
                       nullptr,
                       &(self->tid));
    if (result == 0) {
        self->set_cached_pid(gettid());
        android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_DISABLED);
        __set_stack_and_tls_vma_name(true);
        __bionic_atfork_run_child();      // fork 完成执行子进程回调方法
    } else {
        __bionic_atfork_run_parent();     // fork 完成执行父进程回调方法
    }
    return result;
}

2.11 Zygote.callPostForkChildHooks()

// frameworks/base/core/java/com/android/internal/os/Zygote.java

public final class Zygote {

    private static void callPostForkChildHooks(int runtimeFlags, boolean isSystemServer,
            boolean isZygote, String instructionSet) {
        // 调用 ZygoteHooks.postForkChild() 方法
        ZygoteHooks.postForkChild(runtimeFlags, isSystemServer, isZygote, instructionSet);
    }

}

2.12 ZygoteHooks.postForkChild()

// libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java

public final class ZygoteHooks {

    public static void postForkChild(int runtimeFlags, boolean isSystemServer, boolean isZygote,
            String instructionSet) {
        nativePostForkChild(token, runtimeFlags, isSystemServer, isZygote, instructionSet);
        // 设置新进程 Random 随机数种子为当前系统时间
        Math.setRandomSeedInternal(System.currentTimeMillis());
    }

}

2.13 ZygoteHooks.nativePostForkChild()

// libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java

public final class ZygoteHooks {

    // Hook for all child processes post forking.
    private static native void nativePostForkChild(long token, int runtimeFlags,
                                                   boolean isSystemServer, boolean isZygote,
                                                   String instructionSet);

}

// art/runtime/native/dalvik_system_ZygoteHooks.cc

static void ZygoteHooks_nativePostForkChild(JNIEnv* env,
                                            jclass,
                                            jlong token,
                                            jint runtime_flags,
                                            jboolean is_system_server,
                                            jboolean is_zygote,
                                            jstring instruction_set) {
    DCHECK(!(is_system_server && is_zygote));
    Runtime::Current()->SetAsZygoteChild(is_system_server, is_zygote);

    // 记录当前线程
    Thread* thread = reinterpret_cast<Thread*>(token);
    // 设置新进程的主线程 id
    thread->InitAfterFork();
    ... ...

    if (instruction_set != nullptr && !is_system_server) {
        ScopedUtfChars isa_string(env, instruction_set);
        InstructionSet isa = GetInstructionSetFromString(isa_string.c_str());
        Runtime::NativeBridgeAction action = Runtime::NativeBridgeAction::kUnload;
        if (isa != InstructionSet::kNone && isa != kRuntimeISA) {
            action = Runtime::NativeBridgeAction::kInitialize;
        }
        // 调用 InitNonZygoteOrPostFork() 函数
        runtime->InitNonZygoteOrPostFork(env, is_system_server, is_zygote, action, isa_string.c_str());
    } else {
        runtime->InitNonZygoteOrPostFork(
            env,
            is_system_server,
            is_zygote,
            Runtime::NativeBridgeAction::kUnload,
            /*isa=*/ nullptr,
            profile_system_server);
    }
}

2.14 runtime.InitNonZygoteOrPostFork()

// art/runtime/runtime.cc

void Runtime::InitNonZygoteOrPostFork(
    JNIEnv* env,
    bool is_system_server,
    // This is true when we are initializing a child-zygote. It requires
    // native bridge initialization to be able to run guest native code in
    // doPreload().
    bool is_child_zygote,
    NativeBridgeAction action,
    const char* isa,
    bool profile_system_server) {
    if (is_native_bridge_loaded_) {
        switch (action) {
            case NativeBridgeAction::kUnload:
                UnloadNativeBridge();                      // 卸载用于跨平台的桥连库
                is_native_bridge_loaded_ = false;
                break;

            case NativeBridgeAction::kInitialize:
                InitializeNativeBridge(env, isa);          // 初始化用于跨平台的桥连库
                break;
        }
    }
    ... ...

    // 创建 Java 堆处理的线程池
    heap_->CreateThreadPool();
    ... ...

    //重置 gc 性能数据,以保证进程在创建之前的 GCs 不会计算到当前 app 上
    heap_->ResetGcPerformanceInfo();
    StartSignalCatcher();    // 设置信号处理函数

    ScopedObjectAccess soa(Thread::Current());
    ... ...

    GetRuntimeCallbacks()->StartDebugger();
}

2.15 ZygoteHooks.postForkCommon()

// libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java

public final class ZygoteHooks {

    public static void postForkCommon() {
        // Notify the runtime before creating new threads.
        nativePostZygoteFork();
        Daemons.startPostZygoteFork();
    }

}

2.16 Daemons.startPostZygoteFork()

// libcore/libart/src/main/java/java/lang/Daemons.java

public final class Daemons {

    private static final Daemon[] DAEMONS = new Daemon[] {
            HeapTaskDaemon.INSTANCE,
            ReferenceQueueDaemon.INSTANCE,
            FinalizerDaemon.INSTANCE,
            FinalizerWatchdogDaemon.INSTANCE,
    };

    public static void startPostZygoteFork() {
        postZygoteFork = true;
        for (Daemon daemon : DAEMONS) {
            daemon.startPostZygoteFork();
        }
    }

}

ZygoteHooks.postForkCommon() 的主要功能是在 fork 新进程后,启动 Zygote 的 4 个 Daemon线程,java堆整理,引用队列,以及析构线程。

2.17 源码流程图(Zygote)

函数调用关系流程图.png

至此,App 进程已完成了创建的所有工作,接下来就是开始新创建的 App 进程的工作。

前面我们提到过:在 ZygoteConnection.processOneCommand() 方法中,zygote 进程执行完 forkAndSpecialize() 后,新创建的 App 进程便进入 handleChildProc() 方法。


三、APP 进程

3.1 ZygoteConnection.handleChildProc()

// frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

class ZygoteConnection {

    private Runnable handleChildProc(ZygoteArguments parsedArgs,
            FileDescriptor pipeFd, boolean isZygote) {
        // 关闭 Zygote 的 socket 两端的连接
        closeSocket();

        // 设置进程名
        Zygote.setAppProcessName(parsedArgs, TAG);

        // End of the postFork event.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        if (parsedArgs.mInvokeWith != null) {
            // 用于检测进程内存泄露或溢出时场景而设计
            WrapperInit.execApplication(parsedArgs.mInvokeWith,
                    parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(),
                    pipeFd, parsedArgs.mRemainingArgs);

            // Should not get here.
            throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
        } else {
            if (!isZygote) {
                // 执行目标类的 main() 方法
                return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mDisabledCompatChanges,
                        parsedArgs.mRemainingArgs, null /* classLoader */);
            } else {
                return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mRemainingArgs, null /* classLoader */);
            }
        }
    }

}

3.2 ZygoteInit.zygoteInit()

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

public class ZygoteInit {

    public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
            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();    // 重定向 log 输出

        RuntimeInit.commonInit();            // 通用的一些初始化
        ZygoteInit.nativeZygoteInit();       // zygote 初始化
        // 应用初始化
        return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
                classLoader);
    }

}

3.2.1 RuntimeInit.redirectLogStreams()

// frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

public class RuntimeInit {

    @UnsupportedAppUsage
    protected static final void commonInit() {
        LoggingHandler loggingHandler = new LoggingHandler();
        RuntimeHooks.setUncaughtExceptionPreHandler(loggingHandler);
        // 设置默认的未捕捉异常处理方法
        Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler));

        // 设置时区,中国时区为 "Asia/Shanghai" 
        RuntimeHooks.setTimeZoneIdSupplier(() -> SystemProperties.get("persist.sys.timezone"));

        //重置 log 配置
        LogManager.getLogManager().reset();
        new AndroidConfig();

        // 设置默认的 HTTP User-agent 格式,用于 HttpURLConnection
        String userAgent = getDefaultUserAgent();
        System.setProperty("http.agent", userAgent);

        // 设置 socket 的 tag,用于网络流量统计
        NetworkManagementSocketTagger.install();

        String trace = SystemProperties.get("ro.kernel.android.tracing");
        if (trace.equals("1")) {
            Slog.i(TAG, "NOTE: emulator trace profiling enabled");
            Debug.enableEmulatorTraceOutput();
        }

        initialized = true;
    }

}

3.2.2 ZygoteInit.nativeZygoteInit()

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

public class ZygoteInit {

    private static final native void nativeZygoteInit();

}

// frameworks/base/core/jni/AndroidRuntime.cpp

static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();    // 此处的 gCurRuntime 为 AppRuntime
}

// frameworks/base/cmds/app_process/app_main.cpp

class AppRuntime : public AndroidRuntime
{
public:

    virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();    // 启动新 binder 线程
    }

}

3.2.3 RuntimeInit.applicationInit()

// frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

public class RuntimeInit {

    protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {

        // true 代表应用程序退出时不调用 AppRuntime.onExit(),否则会在退出前调用
        nativeSetExitWithoutCleanup(true);

        // 设置虚拟机的内存利用率参数值为 0.75
        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
        VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);

        // 解析参数
        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
        // 此处 args.startClass 为 "android.app.ActivityThread"
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }

}

3.3 RuntimeInit.findStaticMain()

// frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

public class RuntimeInit {

    protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        Class<?> cl;

        try {
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        }

        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }

        // 通过抛出异常,回到 ZygoteInit.main(),这样做好处是能清空栈帧,提高栈帧利用率
        // m: main() 方法
        // argv: ActivityThread
        // 调用 MethodAndArgsCaller 的 run() 方法
        return new MethodAndArgsCaller(m, argv);
    }

}

3.4 new MethodAndArgsCaller()

// frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

public class RuntimeInit {

    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 {
                // 根据传递过来的参数,此处反射调用 ActivityThread.main() 方法
                mMethod.invoke(null, new Object[] { 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);
            }
        }
    }

}

3.5 ActivityThread.main()

// frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread extends ClientTransactionHandler {

    public static void main(String[] args) {
        ... ...

        Environment.initForCurrentUser();
        ... ...

        Looper.prepareMainLooper();    // 创建主线程 looper
        ... ...

        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);    // attach 到系统进程
        ... ...

        Looper.loop();    // 主线程进入循环状态

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

}

至此,进程创建流程分析完毕!