原文来自于 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 层,包含 ActivityManagerPowerManager 等各种系统服务;
  • Zygote 进程:是 Android 系统的首个 Java 进程,Zygote 是所有 Java 进程的父进程,包括 system_server 进程以及所有的 App 进程都是 Zygote 的子进程,注意这里说的是子进程,而非子线程。

二、 system_server 发起请求

1.PRCS.start

Process.javaAndroidCodeSearch 中竟然搜索不出来 (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) {
// 【见 2】
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) {
// TODO (chriswailes): Is there a better place to check this value?
if (fetchUsapPoolEnabledPropWithMinInterval()) {
informZygotesOfUsapPoolStatus();
}

try {
// 调用 startViaZygote() 方法 【见 3】
return startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ 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) {
// 方法 1:openZygoteSocketIfNeeded() 见 【 3.1】
// 方法 2:zygoteSendArgsAndGetResult()
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 {
// 向主 Zygote 发起连接操作
attemptConnectionToPrimaryZygote();

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

if (mZygoteSecondarySocketAddress != null) {
// 向第二个 Zygote 发起连接操作
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()) {
// 向主 zygote 发起 connect() 操作
primaryZygoteState =
ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress);

maybeSetApiDenylistExemptions(primaryZygoteState, false);
maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
}
}

private void attemptConnectionToSecondaryZygote() throws IOException {
if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
// 当主 zygote 没能匹配成功,则采用第二个 zygote,发起 connect() 操作
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();

//等待 socket 服务端(即 zygote)返回新创建的进程 pid;
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() 方法通过 socketZygote 进程发送消息,这是便会唤醒 Zygote 进程,来响应 socket 客户端的请求(即 system_server 端),接下来的操作便是在 Zygote 来创建进程

三、Zygote 创建进程

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