原文来自于 Gityuan 理解Android进程创建流程 源码更新于 AndroidCodeSearch (现在是 Android 11) ,老版本代码查看于 opersys
1 2 3 4 frameworks/base/core/java/android/os/ - Process.java (PRCS) - ZygoteProcess.java (ZP)
一、准备知识 本文要介绍的是进程的创建,先简单说说进程与线程的区别。
进程: 每个 App 在启动前必须先创建一个进程,该进程是由 Zygote fork 出来的,进程具有独立的资源空间,用于承载 App 上运行的各种 Activity/Service 等组件。进程对于上层应用来说是完全不可见的,这也是 google 有意为之,让 App 程序都是运行在 Android Runtime 。大多数情况一个 App 就运行在一个进程中,除非在 AndroidManifest.xml 中配置 Android:process 属性,或通过 native 代码 fork 进程。
线程: 线程对应用开发者来说非常熟悉,比如每次 new Thread().start() 都会创建一个新的线程,该线程并没有自己独立的地址空间,而是与其所在进程之间资源共享。从 Linux 角度来说进程与线程都是一个 task_struct 结构体,除了是否共享资源外,并没有其他本质的区别。
在接下来的文章,会涉及到 system_server 进程和 Zygote 进程,下面简要这两个进程:
system_server 进程:是用于管理整个 Java framework 层,包含 ActivityManager ,PowerManager 等各种系统服务;
Zygote 进程:是 Android 系统的首个 Java 进程,Zygote 是所有 Java 进程的父进程,包括 system_server 进程以及所有的 App 进程都是 Zygote 的子进程,注意这里说的是子进程,而非子线程。
二、 system_server 发起请求 1.PRCS.start Process.java 在 AndroidCodeSearch 中竟然搜索不出来 (2021/1/22) ,请看上面的路径。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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, ... boolean bindMountAppStorageDirs, @Nullable String[] zygoteArgs) { return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges, pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData, bindMountAppStorageDirs, zygoteArgs); }
2 ZP.start 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public final Process.ProcessStartResult start (@NonNull final String processClass, final String niceName, int uid, int gid, @Nullable int [] gids, ... boolean bindMountAppStorageDirs, @Nullable String[] zygoteArgs) { if (fetchUsapPoolEnabledPropWithMinInterval()) { informZygotesOfUsapPoolStatus(); } try { return startViaZygote(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, false , packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges, pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData, bindMountAppStorageDirs, 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.ZP.startViaZygote 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 private Process.ProcessStartResult startViaZygote (@NonNull final String processClass, @Nullable final String niceName, final int uid, final int gid, ... @Nullable String[] extraArgs) throws ZygoteStartFailedEx { ArrayList<String> argsForZygote = new ArrayList<>(); 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) { return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), zygotePolicyFlags, argsForZygote); } }
3.1 ZP.openZygoteSocketIfNeeded openZygoteSocketIfNeeded(abi) 方法是根据当前的 abi 来选择与 zygote 还是 zygote64 来进行通信。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 private ZygoteState openZygoteSocketIfNeeded (String abi) throws ZygoteStartFailedEx { try { attemptConnectionToPrimaryZygote(); if (primaryZygoteState.matches(abi)) { return primaryZygoteState; } if (mZygoteSecondarySocketAddress != null ) { attemptConnectionToSecondaryZygote(); 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()) { primaryZygoteState = ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress); maybeSetApiDenylistExemptions(primaryZygoteState, false ); maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState); } } private void attemptConnectionToSecondaryZygote () throws IOException { if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) { secondaryZygoteState = ZygoteState.connect(mZygoteSecondarySocketAddress, mUsapPoolSecondarySocketAddress); maybeSetApiDenylistExemptions(secondaryZygoteState, false ); maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState); } }
4.ZP.zygoteSendArgsAndGetResult 这个方法的主要功能是通过 socket 通道向 Zygote 进程发送一个参数列表,然后进入阻塞等待状态,直到远端的 socket 服务端发送回来新创建的进程 pid 才返回。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 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(); result.pid = zygoteInputStream.readInt(); result.usingWrapper = zygoteInputStream.readBoolean(); if (result.pid < 0 ) { throw new ZygoteStartFailedEx("fork() failed" ); } return result; } catch (IOException ex) { zygoteState.close(); throw new ZygoteStartFailedEx(ex); } }
既然 system_server 进程的 zygoteSendArgsAndGetResult() 方法通过 socket 向 Zygote 进程发送消息,这是便会唤醒 Zygote 进程,来响应 socket 客户端的请求(即 system_server 端),接下来的操作便是在 Zygote 来创建进程
三、Zygote 创建进程 Zygote 进程是由 init 进程创建的,进程启动之后便会调用 ZygoteInit.main() 方法,经过创建 socket 管道,预加载资源后,调用 runSelectLoop()方法。