Android系统启动系列7 进程创建流程

一 概述

本文要介绍的是进程的创建,先简单说说进程与线程的区别。

1.1 进程线程介绍

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

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

在接下来的介绍中,会涉及到 system_server 进程和 zygote 进程,下面重复简要介绍下这两个进程:

  • system_server 进程:是用于管理整个 Java framework 层,包含 AMS,PMS 等各种系统服务
  • zygote 进程:是 Android 系统的首个 Java 进程,zygote 是所有 Java 进程的父进程,包括 system_server 进程以及所有的 App 进程都是 zygote 的子进程,注意这里说的是子进程,而非子线程

1.2 涉及代码

/libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
/libcore/libart/src/main/java/java/lang/Daemons.java
/libcore/dalvik/src/main/java/dalvik/system/runtime.cc
/art/runtime/native/dalvik_system_ZygoteHooks.cc
/art/runtime/runtime.cc
/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp	 
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
/frameworks/base/core/java/com/android/internal/os/Zygote.java
/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
/frameworks/base/services/java/com/android/server/SystemServer.java
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
/frameworks/base/services/core/java/com/android/server/am/ProcessList.java
/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
/frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java
/frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
/frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java
/frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
/frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
/frameworks/base/services/core/java/com/android/server/wm/ClientLifecycleManager.java
/frameworks/base/core/java/android/os/Process.java
/frameworks/base/core/java/android/os/ZygoteProcess.java
/frameworks/base/core/java/android/app/LauncherActivity.java
/frameworks/base/core/java/android/app/ActivityThread.java
/frameworks/base/core/java/android/app/Activity.java
/frameworks/base/core/java/android/app/ActivityManagerInternal.java
/frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
/frameworks/base/core/java/android/app/servertransaction/ClientTransaction.aidl
/frameworks/base/core/java/android/app/ClientTransactionHandler.java
/frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
/frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java
/frameworks/base/core/java/android/app/Instrumentation.java
/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

二 架构

2.1 进程创建图

对于大多数的应用开发者来说创建线程比较熟悉,而对于创建进程并没有太多的概念。对于系统工程师或者高级开发者,还是很有必要了解 Android 系统是如何一步步地创建出一个进程的。先来看一张进程创建过程的简要图:

在这里插入图片描述

  • App 发起进程:当从桌面启动应用,则发起进程便是 Launcher 所在进程;当从某 App 内启动远程进程,则发送进程便是该 App 所在进程。发起进程先通过 binder 发送消息给 system_server 进程
  • system_server 进程:调用 Process.start() 方法,通过 socket 向 zygote 进程发送创建新进程的请求
  • zygote 进程:在执行 ZygoteInit.main() 后便进入 runSelectLoop() 循环体内,当有客户端连接时便会执行 ZygoteConnection.runOnce() 方法,再经过层层调用后 fork 出新的应用进程
  • 新进程:执行 handleChildProc 方法,最后调用 ActivityThread.main() 方法

下图是详细调用栈
在这里插入图片描述

三 system_server发起请求

3.1 Process.start

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

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,
                                           int runtimeFlags,
                                           int mountExternal,
                                           int targetSdkVersion,
                                           @Nullable String seInfo,
                                           @NonNull String abi,
                                           @Nullable String instructionSet,
                                           @Nullable String appDataDir,
                                           @Nullable String invokeWith,
                                           @Nullable String packageName,
                                           @Nullable String[] zygoteArgs) {
   
        return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, packageName,
                    /*useUsapPool=*/ true, zygoteArgs);
    }

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

public final Process.ProcessStartResult start(@NonNull final String processClass,
                                                  final String niceName,
                                                  int uid, int gid, @Nullable int[] gids,
                                                  ........
                                                  boolean useUsapPool,
                                                  @Nullable String[] zygoteArgs) {
   
        // TODO (chriswailes): Is there a better place to check this value?
        if (fetchUsapPoolEnabledPropWithMinInterval()) {
   
            informZygotesOfUsapPoolStatus();
        }
        try {
   
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, false,
                    packageName, useUsapPool, zygoteArgs);
        } catch (ZygoteStartFailedEx ex) {
   
            Log.e(LOG_TAG,
                    "Starting VM process through Zygote failed");
            throw new RuntimeException(
                    "Starting VM process through Zygote failed", ex);
        }
    }

3.2 ZygoteProcess.startViaZygote

private Process.ProcessStartResult startViaZygote(@NonNull final String processClass,
                                                      @Nullable final String niceName,
                                                      final int uid, final int gid,
                                                      @Nullable final int[] gids,
                                                      ........
                                                      @Nullable String[] extraArgs)
                                                      throws ZygoteStartFailedEx {
   
        ArrayList<String> argsForZygote = new ArrayList<>();
        // --runtime-args, --setuid=, --setgid=,
        // and --setgroups= must go first
        argsForZygote.add("--runtime-args");
        argsForZygote.add("--setuid=" + uid);
        argsForZygote.add("--setgid=" + gid);
        argsForZygote.add("--runtime-flags=" + runtimeFlags);
        if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
   
            argsForZygote.add("--mount-external-default");
        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {
   
            argsForZygote.add("--mount-external-read");
        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
   
            argsForZygote.add("--mount-external-write");
        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_FULL) {
   
            argsForZygote.add("--mount-external-full");
        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_INSTALLER) {
   
            argsForZygote.add("--mount-external-installer");
        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_LEGACY) {
   
            argsForZygote.add("--mount-external-legacy");
        }
        argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
        ........
        if (niceName != null) {
   
            argsForZygote.add("--nice-name=" + niceName);
        }
        ........
        if (startChildZygote) {
   
            argsForZygote.add("--start-child-zygote");
        }
        if (packageName != null
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值