Skytoby

Android进程创建流程分析

Android进程创建流程分析

基于Android10.0,分析进程的创建过程

一、概述

每个app在启动前都必须创建一个进程,这个进程是由zygote fork而来,进程具有独立的资源空间,用于app上运行的各种Activity、Service等组件。大多数情况下一个应用运行在一个进程中,除非在AndroidManifest.xml中配置Android:process属性,或者通过Native代码fork进程。相对于线程,线程没有独立的地址空间,与其所在进程之间资源共享。

Android系统根据进程的重要性主要分为前台进程、可见进程、服务进程、后台进程、空进程。为了回收系统资源,系统会根据重要性高低来清除进程。

下图是进程的创建过程

1.APP发起进程:当从桌面启动应用,则发起进程是Launcher所在进程;当从某App内启动远程进程,则发送进程是该app所在的进程。发送进程通过binder发送消息给systemserver进程。

2.systemserver进程:调用Process.start方法,通过socket向zygote进程发送创建新进程的请求。

3.zygote进程:执行ZygoteInit.main进入runSelectLoop循环体内,当有客户端连接时,便会执行ZygoteConnection.processOneCommand方法,经过层层调用fork新的应用进程。

4.新进程:执行handleChildProc方法,最后调用ActivityThread.main方法。

下面将从进程的角度分析进程创建的过程。

二、systemserver发起请求

1. Process.start

[->Process.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
String[] zygoteArgs) {
return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith,
/*useBlastulaPool=*/ true, zygoteArgs);
}
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
public final Process.ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
boolean useBlastulaPool,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith,
/*startChildZygote=*/false,
useBlastulaPool, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
throw new RuntimeException(
"Starting VM process through Zygote failed", ex);
}
}

2. Process.startViaZygote

[->ZygoteProcess.java]

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
private Process.ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
boolean startChildZygote,
boolean useBlastulaPool,
String[] extraArgs)
throws ZygoteStartFailedEx {
ArrayList<String> argsForZygote = new ArrayList<String>();

// --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");
}
argsForZygote.add("--target-sdk-version=" + targetSdkVersion);

// --setgroups is a comma-separated list
if (gids != null && gids.length > 0) {
StringBuilder sb = new StringBuilder();
sb.append("--setgroups=");

int sz = gids.length;
for (int i = 0; i < sz; i++) {
if (i != 0) {
sb.append(',');
}
sb.append(gids[i]);
}

argsForZygote.add(sb.toString());
}

if (niceName != null) {
argsForZygote.add("--nice-name=" + niceName);
}

if (seInfo != null) {
argsForZygote.add("--seinfo=" + seInfo);
}

if (instructionSet != null) {
argsForZygote.add("--instruction-set=" + instructionSet);
}

if (appDataDir != null) {
argsForZygote.add("--app-data-dir=" + appDataDir);
}

if (invokeWith != null) {
argsForZygote.add("--invoke-with");
argsForZygote.add(invokeWith);
}

if (startChildZygote) {
argsForZygote.add("--start-child-zygote");
}

argsForZygote.add(processClass);

if (extraArgs != null) {
for (String arg : extraArgs) {
argsForZygote.add(arg);
}
}

synchronized(mLock) {
//见第3节
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
useBlastulaPool,
argsForZygote);
}
}

该过程主要是配置argsForZygote列表信息,列表信息保存了uid,gid,targetSdkVersion,appDataDir等信息。

3. zygoteSendArgsAndGetResult

[->ZygoteProcess.java]

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, boolean useBlastulaPool, ArrayList<String> args)
throws ZygoteStartFailedEx {
// Throw early if any of the arguments are malformed. This means we can
// avoid writing a partial response to the zygote.
for (String arg : args) {
if (arg.indexOf('/n') >= 0) {
throw new ZygoteStartFailedEx("embedded newlines not allowed");
}
}

/*
* See com.android.internal.os.ZygoteArguments.parseArgs()
* Presently the wire format to the zygote process is:
* a) a count of arguments (argc, in essence)
* b) a number of newline-separated argument strings equal to count
*
* After the zygote process reads these it will write the pid of
* the child or -1 on failure, followed by boolean to
* indicate whether a wrapper process was used.
*/
String msgStr = Integer.toString(args.size()) + "/n"
+ String.join("/n", args) + "/n";

// Should there be a timeout on this?
//这里等待创建进程返回是否加timeout?
Process.ProcessStartResult result = new Process.ProcessStartResult();

// TODO (chriswailes): Move branch body into separate function.
if (useBlastulaPool && Zygote.BLASTULA_POOL_ENABLED && isValidBlastulaCommand(args)) {
LocalSocket blastulaSessionSocket = null;
//blastulaSessionSocket进入这个分支
try {
blastulaSessionSocket = zygoteState.getBlastulaSessionSocket();

final BufferedWriter blastulaWriter =
new BufferedWriter(
new OutputStreamWriter(blastulaSessionSocket.getOutputStream()),
Zygote.SOCKET_BUFFER_SIZE);
final DataInputStream blastulaReader =
new DataInputStream(blastulaSessionSocket.getInputStream());

blastulaWriter.write(msgStr);
blastulaWriter.flush();

//等待socket服务端返回新创建的进程pid
result.pid = blastulaReader.readInt();
// Blastulas can't be used to spawn processes that need wrappers.
result.usingWrapper = false;

if (result.pid < 0) {
throw new ZygoteStartFailedEx("Blastula specialization failed");
}

return result;
} catch (IOException ex) {
// If there was an IOException using the blastula pool we will log the error and
// attempt to start the process through the Zygote.
Log.e(LOG_TAG, "IO Exception while communicating with blastula pool - "
+ ex.toString());
} finally {
try {
blastulaSessionSocket.close();
} catch (IOException ex) {
Log.e(LOG_TAG, "Failed to close blastula session socket: " + ex.getMessage());
}
}
}

try {
final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;

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

// Always read the entire result from the input stream to avoid leaving
// bytes in the stream for future process starts to accidentally stumble
// upon.
//等待socket服务端返回新创建的进程pid
result.pid = zygoteInputStream.readInt();
result.usingWrapper = zygoteInputStream.readBoolean();
} catch (IOException ex) {
zygoteState.close();
Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "
+ ex.toString());
throw new ZygoteStartFailedEx(ex);
}

if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}

return result;
}

这个方法主要是通过socket通道向zygote进程发送一个参数列表信息,然后进入阻塞等待状态,直到远端的socket服务端发送回来新创建的进程pid才返回。

3.1 openZygoteSocketIfNeeded

[->ZygoteProcess.java]

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
private ZygoteState openZygoteSocketIfNeeded(String abi)
throws ZygoteStartFailedEx {

Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");

if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
try {
//向主zygote发起connect操作
primaryZygoteState =
ZygoteState.connect(mZygoteSocketAddress, mBlastulaPoolSocketAddress);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
}

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

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

// The primary zygote didn't match. Try the secondary.
if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
try {
//当主zygote不匹配,则采用第二个zygote发起connect连接
secondaryZygoteState =
ZygoteState.connect(mZygoteSecondarySocketAddress,
mBlastulaPoolSecondarySocketAddress);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
}

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

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

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

这个方法主要是根据abi来选择与zygote还是zygote64来进行通信。

在systemserver进程的zygoteSendArgsAndGetResult方法通过socket向zygote发送消息,这时会唤醒Zygote进程,来响应systemserver客户端的请求,下面是zygote来创建进程。

三、zygote创建进程

在systemserver启动过程上中有介绍zygote进程启动,它是由init进程创建,进程启动之后调用ZygoteInit.main方法,经过socket管道,预加载资源后,进入runSelectLoop方法。

4.ZygoteInit.main

[->ZygoteInit.java]

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer();

// Mark zygote start. This ensures that thread creation will throw
// an error.
ZygoteHooks.startZygoteNoThreadCreation();

// Zygote goes into its own process group.
try {
Os.setpgid(0, 0);
} catch (ErrnoException ex) {
throw new RuntimeException("Failed to setpgid(0,0)", ex);
}

Runnable caller;
try {
// Report Zygote start time to tron unless it is a runtime restart
if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {
MetricsLogger.histogram(null, "boot_zygote_init",
(int) SystemClock.elapsedRealtime());
}

String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
Trace.TRACE_TAG_DALVIK);
bootTimingsTraceLog.traceBegin("ZygoteInit");
RuntimeInit.enableDdms();

boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if ("--enable-lazy-preload".equals(argv[i])) {
enableLazyPreload = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}

if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}

// TODO (chriswailes): Wrap these three calls in a helper function?
final String blastulaSocketName =
socketName.equals(ZygoteProcess.ZYGOTE_SOCKET_NAME)
? ZygoteProcess.BLASTULA_POOL_SOCKET_NAME
: ZygoteProcess.BLASTULA_POOL_SECONDARY_SOCKET_NAME;
//为zygote注册socket
zygoteServer.createZygoteSocket(socketName);
Zygote.createBlastulaSocket(blastulaSocketName);

Zygote.getSocketFDs(socketName.equals(ZygoteProcess.ZYGOTE_SOCKET_NAME));

// In some configurations, we avoid preloading resources and classes eagerly.
// In such cases, we will preload things prior to our first fork.
if (!enableLazyPreload) {
bootTimingsTraceLog.traceBegin("ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
//预加载资源
preload(bootTimingsTraceLog);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else {
Zygote.resetNicePriority();
}

// Do an initial gc to clean up after startup
bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
gcAndFinalize();
bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC

bootTimingsTraceLog.traceEnd(); // ZygoteInit
// Disable tracing so that forked processes do not inherit stale tracing tags from
// Zygote.
Trace.setTracingEnabled(false, 0);

Zygote.nativeSecurityInit();

// Zygote process unmounts root storage spaces.
Zygote.nativeUnmountStorageOnInit();

ZygoteHooks.stopZygoteNoThreadCreation();

if (startSystemServer) {
//启动systemserver进程
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);

// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}

// If the return value is null then this is the zygote process
// returning to the normal control flow. If it returns a Runnable
// object then this is a blastula that has finished specializing.
// 初始化胚胎池
caller = Zygote.initBlastulaPool();

if (caller == null) {
Log.i(TAG, "Accepting command socket connections");
// 当接收到创建进程的请求时唤醒并执行相应工作
// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
caller = zygoteServer.runSelectLoop(abiList);
}
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
zygoteServer.closeServerSocket();
}

// We're in the child process and have exited the select loop. Proceed to execute the
// command.
if (caller != null) {
caller.run();
}
}

5.ZS.runSelectLoop

[->ZygoteServer.java]

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/**
* 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.
*/
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
//mZygoteSocket是socket通信中的服务端即zygote进程,保存在fds[0]中
socketFDs.add(mZygoteSocket.getFileDescriptor());
peers.add(null);

while (true) {
int[] blastulaPipeFDs = Zygote.getBlastulaPipeFDs();

// Space for all of the socket FDs, the Blastula Pool Event FD, and
// all of the open blastula read pipe FDs.
//pollFDs包括socket、Blastula Pool Event 和open blastula read pipe FDs
StructPollfd[] pollFDs =
new StructPollfd[socketFDs.size() + 1 + blastulaPipeFDs.length];

int pollIndex = 0;
for (FileDescriptor socketFD : socketFDs) {
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = socketFD;
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
}

final int blastulaPoolEventFDIndex = pollIndex;
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = Zygote.sBlastulaPoolEventFD;
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;

for (int blastulaPipeFD : blastulaPipeFDs) {
FileDescriptor managedFd = new FileDescriptor();
managedFd.setInt$(blastulaPipeFD);

pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = managedFd;
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
}

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

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

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

} else if (pollIndex < blastulaPoolEventFDIndex) {
// Session socket accepted from the Zygote server socket
// 从zygote server中的socket
try {
ZygoteConnection connection = peers.get(pollIndex);
final Runnable command = connection.processOneCommand(this);

if (mIsForkChild) {
// We're in the child. We should always have a command to run at this
// stage if processOneCommand hasn't called "exec".
if (command == null) {
throw new IllegalStateException("command == null");
}

return command;
} else {
// We're in the server - we should never have any commands to run.
if (command != null) {
throw new IllegalStateException("command != null");
}

// We don't know whether the remote side of the socket was closed or
// not until we attempt to read from it from processOneCommand. This
// shows up as a regular POLLIN event in our regular processing loop.
if (connection.isClosedByPeer()) {
connection.closeSocket();
peers.remove(pollIndex);
socketFDs.remove(pollIndex);
}
}
} catch (Exception e) {
if (!mIsForkChild) {
// We're in the server so any exception here is one that has taken place
// pre-fork while processing commands or reading / writing from the
// control socket. Make a loud noise about any such exceptions so that
// we know exactly what failed and why.

Slog.e(TAG, "Exception executing zygote command: ", e);

// Make sure the socket is closed so that the other end knows
// immediately that something has gone wrong and doesn't time out
// waiting for a response.
ZygoteConnection conn = peers.remove(pollIndex);
conn.closeSocket();

socketFDs.remove(pollIndex);
} else {
// We're in the child so any exception caught here has happened post
// fork and before we execute ActivityThread.main (or any other main()
// method). Log the details of the exception and bring down the process.
Log.e(TAG, "Caught post-fork exception in child process.", e);
throw e;
}
} finally {
// Reset the child flag, in the event that the child process is a child-
// zygote. The flag will not be consulted this loop pass after the Runnable
// is returned.
mIsForkChild = false;
}
} else {
// Either the blastula pool event FD or a blastula reporting pipe.
// blastula pool event FD或者blastula reporting pipe
// If this is the event FD the payload will be the number of blastulas removed.
// If this is a reporting pipe FD the payload will be the PID of the blastula
// that was just specialized.
long messagePayload = -1;

try {

/**
* Number of bytes sent to the Zygote over blastula pipes or the pool event FD
* public static final int BLASTULA_MANAGEMENT_MESSAGE_BYTES = 8;
*/
byte[] buffer = new byte[Zygote.BLASTULA_MANAGEMENT_MESSAGE_BYTES];
int readBytes = Os.read(pollFDs[pollIndex].fd, buffer, 0, buffer.length);

if (readBytes == Zygote.BLASTULA_MANAGEMENT_MESSAGE_BYTES) {
DataInputStream inputStream =
new DataInputStream(new ByteArrayInputStream(buffer));

messagePayload = inputStream.readLong();
} else {
Log.e(TAG, "Incomplete read from blastula management FD of size "
+ readBytes);
continue;
}
} catch (Exception ex) {
if (pollIndex == blastulaPoolEventFDIndex) {
Log.e(TAG, "Failed to read from blastula pool event FD: "
+ ex.getMessage());
} else {
Log.e(TAG, "Failed to read from blastula reporting pipe: "
+ ex.getMessage());
}

continue;
}

if (pollIndex > blastulaPoolEventFDIndex) {
Zygote.removeBlastulaTableEntry((int) messagePayload);
}

int[] sessionSocketRawFDs =
socketFDs.subList(1, socketFDs.size())
.stream()
.mapToInt(fd -> fd.getInt$())
.toArray();

final Runnable command = Zygote.fillBlastulaPool(sessionSocketRawFDs);

if (command != null) {
return command;
}
}
}
}
}

第三小节zygoteSendArgsAndGetResult发送请求来建立连接,根据不同的请求做相应的处理:

  • pollIndex小于blastulaPoolEventFDIndex为来自Zygote server socket的请求;

    执行acceptCommandPeer,创建ZygoteConnection对象,并添加socketFDs数值,建立连接后,可以和客户端进行通信,进入processOneCommand方法接受客户端数据,并执行进程创建工作。

  • pollIndex大于等于blastulaPoolEventFDIndex为胚胎池事件FD或者胚胎上报管道;

    读取管道信息,调用fillBlastulaPool方法,创建胚胎(blastula)进程。

5.1 ZC.acceptCommandPeer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* Waits for and accepts a single command connection. Throws
* RuntimeException on failure.
*/
private ZygoteConnection acceptCommandPeer(String abiList) {
try {
return createNewConnection(mZygoteSocket.accept(), abiList);
} catch (IOException ex) {
throw new RuntimeException(
"IOException during accept()", ex);
}
}

protected ZygoteConnection createNewConnection(LocalSocket socket, String abiList)
throws IOException {
return new ZygoteConnection(socket, abiList);
}

客户端发送过来的connect操作,服务端zygote执行accept操作,然后客户端写数据,zygote服务端读数据。

在没有连接的情况下会进入休眠状态,当有新创建的进程发送连接请求时,唤醒zygote进程,创建socket通道,然后执行processOneCommand方法。

6. ZC.processOneCommand

[->ZygoteConnection.java]

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/**
* Reads one start command from the command socket. If successful, a child is forked and a
* {@code Runnable} that calls the childs main method (or equivalent) is returned in the child
* process. {@code null} is always returned in the parent process (the zygote).
*
* If the client closes the socket, an {@code EOF} condition is set, which callers can test
* for by calling {@code ZygoteConnection.isClosedByPeer}.
*/
Runnable processOneCommand(ZygoteServer zygoteServer) {
String args[];
ZygoteArguments parsedArgs = null;
FileDescriptor[] descriptors;

try {
//读取客户端发送过来参数列表
args = Zygote.readArgumentList(mSocketReader);

// TODO (chriswailes): Remove this and add an assert.
descriptors = mSocket.getAncillaryFileDescriptors();
} 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 = -1;
FileDescriptor childPipeFd = null;
FileDescriptor serverPipeFd = null;
//将客户端传递过来的参数,解析成ZygoteArguments对象格式
parsedArgs = new ZygoteArguments(args);

//进行一序列参数判断
if (parsedArgs.mAbiListQuery) {
handleAbiListQuery();
return null;
}

if (parsedArgs.mPidQuery) {
handlePidQuery();
return null;
}

if (parsedArgs.mPreloadDefault) {
handlePreload();
return null;
}

if (parsedArgs.mPreloadPackage != null) {
handlePreloadPackage(parsedArgs.mPreloadPackage, parsedArgs.mPreloadPackageLibs,
parsedArgs.mPreloadPackageLibFileName, parsedArgs.mPreloadPackageCacheKey);
return null;
}

if (parsedArgs.mApiBlacklistExemptions != null) {
handleApiBlacklistExemptions(parsedArgs.mApiBlacklistExemptions);
return null;
}

if (parsedArgs.mHiddenApiAccessLogSampleRate != -1) {
handleHiddenApiAccessLogSampleRate(parsedArgs.mHiddenApiAccessLogSampleRate);
return null;
}

if (parsedArgs.mPermittedCapabilities != 0 || parsedArgs.mEffectiveCapabilities != 0) {
throw new ZygoteSecurityException("Client may not specify capabilities: "
+ "permitted=0x" + Long.toHexString(parsedArgs.mPermittedCapabilities)
+ ", effective=0x" + Long.toHexString(parsedArgs.mEffectiveCapabilities));
}

Zygote.applyUidSecurityPolicy(parsedArgs, peer);
Zygote.applyInvokeWithSecurityPolicy(parsedArgs, peer);

Zygote.applyDebuggerSystemProperty(parsedArgs);
Zygote.applyInvokeWithSystemProperty(parsedArgs);

int[][] rlimits = null;

if (parsedArgs.mRLimits != null) {
rlimits = parsedArgs.mRLimits.toArray(Zygote.INT_ARRAY_2D);
}

int[] fdsToIgnore = null;

if (parsedArgs.mInvokeWith != null) {
try {
FileDescriptor[] pipeFds = Os.pipe2(O_CLOEXEC);
childPipeFd = pipeFds[1];
serverPipeFd = pipeFds[0];
Os.fcntlInt(childPipeFd, F_SETFD, 0);
fdsToIgnore = new int[]{childPipeFd.getInt$(), serverPipeFd.getInt$()};
} catch (ErrnoException errnoEx) {
throw new IllegalStateException("Unable to set up pipe for invoke-with", errnoEx);
}
}

/**
* In order to avoid leaking descriptors to the Zygote child,
* the native code must close the two Zygote socket descriptors
* in the child process before it switches from Zygote-root to
* the UID and privileges of the application being launched.
*
* In order to avoid "bad file descriptor" errors when the
* two LocalSocket objects are closed, the Posix file
* descriptors are released via a dup2() call which closes
* the socket and substitutes an open descriptor to /dev/null.
*/

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

fd = null;

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

try {
if (pid == 0) {
// in child
//子进程执行
zygoteServer.setForkChild();

zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
//见第四大节
return handleChildProc(parsedArgs, descriptors, 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, descriptors, serverPipeFd);
return null;
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}

这里主要是处理客户端返回过来的参数,并调用forkAndSpecialize方法创建进程,返回pid

7.Zygote.forkAndSpecialize

[->Zygote.java]

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
/**
* @return 0 if this is the child, pid of the child
* if this is the parent, or -1 on error.
*/
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,
int targetSdkVersion) {
//见小节8
ZygoteHooks.preFork();
// Resets nice priority for zygote process.
resetNicePriority();
//见小节9
int pid = nativeForkAndSpecialize(
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
fdsToIgnore, startChildZygote, instructionSet, appDataDir);
// Enable tracing as soon as possible for the child process.
if (pid == 0) {
Zygote.disableExecuteOnly(targetSdkVersion);
Trace.setTracingEnabled(true, runtimeFlags);

// Note that this event ends at the end of handleChildProc,
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
}
//见小节12
ZygoteHooks.postForkCommon();
return pid;
}

Zygote进程有4个子线程分别为ReferenceQueueD、FinalizerDaemon、FinalizerWatchd、HeapTaskDaemon,图中的线程名显示并不完整,是由于底层的进程结构体task_struct是由长度16的char型数组保存。

8. ZygoteHooks.preFork

[->ZygoteHooks.java]

1
2
3
4
5
public void preFork() {
Daemons.stop(); //停止4个Daemons子进程
waitUntilAllThreadsStopped(); //等待所有子线程结束
token = nativePreFork(); //完成gc堆得初始化
}

8.1 Daemons.stop

[->Daemons.java]

1
2
3
4
5
6
public static void stop() {
HeapTaskDaemon.INSTANCE.stop(); //Java堆整理线程
ReferenceQueueDaemon.INSTANCE.stop(); //引用队列线程
FinalizerDaemon.INSTANCE.stop(); //析构线程
FinalizerWatchdogDaemon.INSTANCE.stop();//析构监控线程
}

此守护线程stop方式是先调用目标线程的interrupt方法,然后再调用目标线程join方法,等待线程执行完成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* Waits for the runtime thread to stop. This interrupts the thread
* currently running the runnable and then waits for it to exit.
*/
public void stop() {
Thread threadToStop;
synchronized (this) {
threadToStop = thread;
thread = null;
}
if (threadToStop == null) {
throw new IllegalStateException("not running");
}
interrupt(threadToStop);
while (true) {
try {
threadToStop.join();
return;
} catch (InterruptedException ignored) {
} catch (OutOfMemoryError ignored) {
// An OOME may be thrown if allocating the InterruptedException failed.
}
}
}

8.2 waitUntilAllThreadsStopped

[->ZygoteHooks.java]

1
2
3
4
5
6
7
8
9
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,就让出线程数大于1,才退出循环
while (tasks.list().length > 1) {
Thread.yield();
}
}

8.3 nativePreFork

[->dalvik_system_ZygoteHooks.cc]

nativePreFork通过JNI最终调用如下方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static jlong ZygoteHooks_nativePreFork(JNIEnv* env, jclass) {
Runtime* runtime = Runtime::Current();
CHECK(runtime->IsZygote()) << "runtime instance not started with -Xzygote";

runtime->PreZygoteFork();

if (Trace::GetMethodTracingMode() != TracingMode::kTracingInactive) {
// Tracing active, pause it.
Trace::Pause();
}

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

void Runtime::PreZygoteFork() {
//堆的初始化,具体到art虚拟机
heap_->PreZygoteFork();
}

ZygoteHooks.preFork主要功能是停止Zygote的4个Daemon子线程的运行,等待并确保Zygote是单线程(用于fork效率),并等待这些线程的停止,初始化gc堆得工作,并将线程转换为long型并保存到token。

9. nativeForkAndSpecialize

[->com_android_internal_os_Zygote.cpp]

nativeForkAndSpecialize通过JNC调用如下方法

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
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) {
jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);

if (UNLIKELY(managed_fds_to_close == nullptr)) {
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> blastula_pipes = MakeBlastulaPipeReadFDVector();

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

fds_to_close.push_back(gBlastulaPoolSocketFD);

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

//见10小节
pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore);

if (pid == 0) {
//见11小节
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);
}
return pid;
}

10. ForkCommon

[->com_android_internal_os_Zygote.cpp]

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
47
48
49
50
51
52
53
54
55
56
57
58
// 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) {
//设置子进程的signal信号处理函数
SetSignalHandlers();

// Curry a failure function.
auto fail_fn = std::bind(ZygoteFailure, env, is_system_server ? "system_server" : "zygote",
nullptr, _1);

// Temporarily block SIGCHLD during forks. The SIGCHLD handler might
// log, which would result in the logging FDs we close being reopened.
// This would cause failures because the FDs are not whitelisted.
//
// Note that the zygote process is single threaded at this point.
BlockSignal(SIGCHLD, fail_fn);

// Close any logging related FDs before we start evaluating the list of
// file descriptors.
__android_log_close();
stats_log_close();

// If this is the first fork for this zygote, create the open FD table. If
// it isn't, we just need to check whether the list of open files has changed
// (and it shouldn't in the normal case).
if (gOpenFdTable == nullptr) {
gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, fail_fn);
} else {
gOpenFdTable->Restat(fds_to_ignore, fail_fn);
}

android_fdsan_error_level fdsan_error_level = android_fdsan_get_error_level();
//fork子进程
pid_t pid = fork();

if (pid == 0) {
// The child process.
PreApplicationInit();

// Clean up any descriptors which must be closed immediately
DetachDescriptors(env, fds_to_close, fail_fn);

// 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);
} else {
ALOGD("Forked child process %d", pid);
}

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

return pid;
}

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

父进程中,fork返回新创建的子进程pid

子进程中,fork返回0

当出现错误(进程数超过上限或者系统内存不足)时,fork返回负数。

fork主要工作是寻找空闲的进程号pid,然后从父进程中拷贝进程信息,例如代码段和数据段,fork后子进程要执行的代码。Zygote进程是所有Android进程的母体,包括systemserver和各个app进程。zygote利用fork方法生成新的进程,对于新进程A复用Zygote进程本身的资源,再加上新进程A相关的资源,构成新的应用进程A.

copy on write过程:当父子进程任何一方修改内存数据时(on-write时机),才发生缺页中断,从而分配新的物理内存(copy操作)。原理:写时拷贝是指子进程与父进程的页表都指向同一物理内存,fork过程只拷贝父进程的页表,并标记这些页表是可读的。父子进程共用同一份物理内存,如果父子进程任一方想要修改这块物理内存,那么就会触发缺页异常,linux收到改中断便会创建新的物理内存,并将这个两个物理内存都设置为可写状态,从而父子进程各自用用独立的物理内存。

10.1 fork

[->bionic/fork.cpp]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int fork() {
__bionic_atfork_run_prepare();

pthread_internal_t* self = __get_thread();
//fork过程,syscall调用
int result = clone(nullptr,
nullptr,
(CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD),
nullptr,
nullptr,
nullptr,
&(self->tid));
if (result == 0) {
// Update the cached pid, since clone() will not set it directly (as
// self->tid is updated by the kernel).
self->set_cached_pid(gettid());
__bionic_atfork_run_child();
} else {
__bionic_atfork_run_parent();
}
return result;
}

在执行clone前后都有相应的回调方法

__bionic_atfork_run_prepare() : fork完成执行子进程回调方法

__bionic_atfork_run_child() : fork完成执行子进程回调方法

__bionic_atfork_run_parent() : fork完成执行父进程回调方法

这个三个方法bionic/pthread_atfork.cpp中,如果有业务需求,可以拓展回调方法

11. SpecializeCommon

[->com_android_internal_os_Zygote.cpp]

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// 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) {
const char* process_name = is_system_server ? "system_server" : "zygote";
auto fail_fn = std::bind(ZygoteFailure, env, process_name, managed_nice_name, _1);
auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);

auto se_info = extract_fn(managed_se_info);
auto nice_name = extract_fn(managed_nice_name);
auto instruction_set = extract_fn(managed_instruction_set);
auto app_data_dir = extract_fn(managed_app_data_dir);

// Keep capabilities across UID change, unless we're staying root.
if (uid != 0) {
EnableKeepCapabilities(fail_fn);
}

SetInheritable(permitted_capabilities, fail_fn);

DropCapabilitiesBoundingSet(fail_fn);

bool use_native_bridge = !is_system_server &&
instruction_set.has_value() &&
android::NativeBridgeAvailable() &&
android::NeedsNativeBridge(instruction_set.value().c_str());

if (use_native_bridge && !app_data_dir.has_value()) {
// The app_data_dir variable should never be empty if we need to use a
// native bridge. In general, app_data_dir will never be empty for normal
// applications. It can only happen in special cases (for isolated
// processes which are not associated with any app). These are launched by
// the framework and should not be emulated anyway.
use_native_bridge = false;
ALOGW("Native bridge will not be used because managed_app_data_dir == nullptr.");
}

MountEmulatedStorage(uid, mount_external, use_native_bridge, fail_fn);

// If this zygote isn't root, it won't be able to create a process group,
// since the directory is owned by root.
//对于非systemserver子进程并且uid==0,则创建进程组
if (!is_system_server && getuid() == 0) {
const int rc = createProcessGroup(uid, getpid());
if (rc != 0) {
if (rc == -EROFS) {
ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?");
} else {
ALOGE("createProcessGroup(%d, %d) failed: %s", uid, 0/*pid*/, strerror(-rc));
}
}
}

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

if (use_native_bridge) {
// Due to the logic behind use_native_bridge we know that both app_data_dir
// and instruction_set contain values.
android::PreInitializeNativeBridge(app_data_dir.value().c_str(),
instruction_set.value().c_str());
}

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

// Must be called when the new process still has CAP_SYS_ADMIN, in this case,
// before changing uid from 0, which clears capabilities. The other
// alternative is to call prctl(PR_SET_NO_NEW_PRIVS, 1) afterward, but that
// breaks SELinux domain transition (see b/71859146). As the result,
// privileged syscalls used below still need to be accessible in app process.
SetUpSeccompFilter(uid);

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

// The "dumpable" flag of a process, which controls core dump generation, is
// overwritten by the value in /proc/sys/fs/suid_dumpable when the effective
// user or group ID changes. See proc(5) for possible values. In most cases,
// the value is 0, so core dumps are disabled for zygote children. However,
// when running in a Chrome OS container, the value is already set to 2,
// which allows the external crash reporter to collect all core dumps. Since
// only system crashes are interested, core dump is disabled for app
// processes. This also ensures compliance with CTS.
int dumpable = prctl(PR_GET_DUMPABLE);
if (dumpable == -1) {
ALOGE("prctl(PR_GET_DUMPABLE) failed: %s", strerror(errno));
RuntimeAbort(env, __LINE__, "prctl(PR_GET_DUMPABLE) failed");
}

if (dumpable == 2 && uid >= AID_APP) {
if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) == -1) {
ALOGE("prctl(PR_SET_DUMPABLE, 0) failed: %s", strerror(errno));
RuntimeAbort(env, __LINE__, "prctl(PR_SET_DUMPABLE, 0) failed");
}
}

// Set process properties to enable debugging if required.
if ((runtime_flags & RuntimeFlags::DEBUG_ENABLE_JDWP) != 0) {
EnableDebugger();
}

if (NeedsNoRandomizeWorkaround()) {
// Work around ARM kernel ASLR lossage (http://b/5817320).
int old_personality = personality(0xffffffff);
int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
if (new_personality == -1) {
ALOGW("personality(%d) failed: %s", new_personality, strerror(errno));
}
}

SetCapabilities(permitted_capabilities, effective_capabilities, permitted_capabilities, fail_fn);
//设置调度策略
SetSchedulerPolicy(fail_fn);

const char* se_info_ptr = se_info.has_value() ? se_info.value().c_str() : nullptr;
const char* nice_name_ptr = nice_name.has_value() ? nice_name.value().c_str() : nullptr;

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

// Make it easier to debug audit logs by setting the main thread's name to the
// nice name rather than "app_process".
if (nice_name.has_value()) {
SetThreadName(nice_name.value());
} else if (is_system_server) {
SetThreadName("system_server");
}

// Unset the SIGCHLD handler, but keep ignoring SIGHUP (rationale in SetSignalHandlers).
//在子进程中,设置信号SIGHUP的处理器恢复默认行为
UnsetChldSignalHandler();

if (is_system_server) {
env->CallStaticVoidMethod(gZygoteClass, gCallPostForkSystemServerHooks);
if (env->ExceptionCheck()) {
fail_fn("Error calling post fork system server hooks.");
}

// Prefetch the classloader for the system server. This is done early to
// allow a tie-down of the proper system server selinux domain.
env->CallStaticVoidMethod(gZygoteInitClass, gCreateSystemServerClassLoader);
if (env->ExceptionCheck()) {
// Be robust here. The Java code will attempt to create the classloader
// at a later point (but may not have rights to use AoT artifacts).
env->ExceptionClear();
}

// TODO(oth): Remove hardcoded label here (b/117874058).
static const char* kSystemServerLabel = "u:r:system_server:s0";
//selinux上下文
if (selinux_android_setcon(kSystemServerLabel) != 0) {
fail_fn(CREATE_ERROR("selinux_android_setcon(%s)", kSystemServerLabel));
}
}
//JNI,调用java方法,调用zygote.callPostForkChildHooks[见11.1]
env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
is_system_server, is_child_zygote, managed_instruction_set);

if (env->ExceptionCheck()) {
fail_fn("Error calling post fork hooks.");
}
}

11.1 callPostForkChildHooks

[->Zygote.java]

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

11.2 postForkChild

[->ZygoteHooks.java]

1
2
3
4
5
public void postForkChild(int runtimeFlags, boolean isSystemServer, boolean isZygote,
String instructionSet) {
nativePostForkChild(token, runtimeFlags, isSystemServer, isZygote, instructionSet);
Math.setRandomSeedInternal(System.currentTimeMillis());
}

11.3 nativePostForkChild

[->dalvik_system_ZygoteHooks.cc]

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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));
//此token由8.3创建,记录着当前线程
Thread* thread = reinterpret_cast<Thread*>(token);
// Our system thread ID, etc, has changed so reset Thread state.
// 设置新进程的主线程id
thread->InitAfterFork();
runtime_flags = EnableDebugFeatures(runtime_flags);
hiddenapi::EnforcementPolicy api_enforcement_policy = hiddenapi::EnforcementPolicy::kNoChecks;
bool dedupe_hidden_api_warnings = true;

if ((runtime_flags & DISABLE_VERIFIER) != 0) {
Runtime::Current()->DisableVerifier();
runtime_flags &= ~DISABLE_VERIFIER;
}

if ((runtime_flags & ONLY_USE_SYSTEM_OAT_FILES) != 0) {
Runtime::Current()->GetOatFileManager().SetOnlyUseSystemOatFiles();
runtime_flags &= ~ONLY_USE_SYSTEM_OAT_FILES;
}

api_enforcement_policy = hiddenapi::EnforcementPolicyFromInt(
(runtime_flags & HIDDEN_API_ENFORCEMENT_POLICY_MASK) >> API_ENFORCEMENT_POLICY_SHIFT);
runtime_flags &= ~HIDDEN_API_ENFORCEMENT_POLICY_MASK;

bool profile_system_server = (runtime_flags & PROFILE_SYSTEM_SERVER) == PROFILE_SYSTEM_SERVER;
runtime_flags &= ~PROFILE_SYSTEM_SERVER;

if (runtime_flags != 0) {
LOG(ERROR) << StringPrintf("Unknown bits set in runtime_flags: %#x", runtime_flags);
}

// Update tracing.
if (Trace::GetMethodTracingMode() != TracingMode::kTracingInactive) {
Trace::TraceOutputMode output_mode = Trace::GetOutputMode();
Trace::TraceMode trace_mode = Trace::GetMode();
size_t buffer_size = Trace::GetBufferSize();

// Just drop it.
Trace::Abort();

// Only restart if it was streaming mode.
// TODO: Expose buffer size, so we can also do file mode.
if (output_mode == Trace::TraceOutputMode::kStreaming) {
static constexpr size_t kMaxProcessNameLength = 100;
char name_buf[kMaxProcessNameLength] = {};
int rc = pthread_getname_np(pthread_self(), name_buf, kMaxProcessNameLength);
std::string proc_name;

if (rc == 0) {
// On success use the pthread name.
proc_name = name_buf;
}

if (proc_name.empty() || proc_name == "zygote" || proc_name == "zygote64") {
// Either no process name, or the name hasn't been changed, yet. Just use pid.
pid_t pid = getpid();
proc_name = StringPrintf("%u", static_cast<uint32_t>(pid));
}

std::string trace_file = StringPrintf("/data/misc/trace/%s.trace.bin", proc_name.c_str());
Trace::Start(trace_file.c_str(),
-1,
buffer_size,
0, // TODO: Expose flags.
output_mode,
trace_mode,
0); // TODO: Expose interval.
if (thread->IsExceptionPending()) {
ScopedObjectAccess soa(env);
thread->ClearException();
}
}
}

bool do_hidden_api_checks = api_enforcement_policy != hiddenapi::EnforcementPolicy::kNoChecks;
DCHECK(!(is_system_server && do_hidden_api_checks))
<< "SystemServer should be forked with EnforcementPolicy::kDisable";
DCHECK(!(is_zygote && do_hidden_api_checks))
<< "Child zygote processes should be forked with EnforcementPolicy::kDisable";
Runtime::Current()->SetHiddenApiEnforcementPolicy(api_enforcement_policy);
Runtime::Current()->SetDedupeHiddenApiWarnings(dedupe_hidden_api_warnings);
if (api_enforcement_policy != hiddenapi::EnforcementPolicy::kNoChecks &&
Runtime::Current()->GetHiddenApiEventLogSampleRate() != 0) {
// Hidden API checks are enabled, and we are sampling access for the event log. Initialize the
// random seed, to ensure the sampling is actually random. We do this post-fork, as doing it
// pre-fork would result in the same sequence for every forked process.
std::srand(static_cast<uint32_t>(NanoTime()));
}

// Clear the hidden API warning flag, in case it was set.
Runtime::Current()->SetPendingHiddenApiWarning(false);

if (is_zygote) {
// If creating a child-zygote, do not call into the runtime's post-fork logic.
// Doing so would spin up threads for Binder and JDWP. Instead, the Java side
// of the child process will call a static main in a class specified by the parent.
return;
}

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;
}
Runtime::Current()->InitNonZygoteOrPostFork(
env, is_system_server, action, isa_string.c_str());
} else {
Runtime::Current()->InitNonZygoteOrPostFork(
env,
is_system_server,
Runtime::NativeBridgeAction::kUnload,
/*isa*/ nullptr,
profile_system_server);
}
}

11.4 InitNonZygoteOrPostFork

[->runtime.cc]

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
47
48
49
50
51
52
53
54
55
56
57
58
void Runtime::InitNonZygoteOrPostFork(
JNIEnv* env,
bool is_system_server,
NativeBridgeAction action,
const char* isa,
bool profile_system_server) {
is_zygote_ = false;

if (is_native_bridge_loaded_) {
switch (action) {
case NativeBridgeAction::kUnload:
//卸载用于跨平台的桥连库
UnloadNativeBridge();
is_native_bridge_loaded_ = false;
break;

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

// Create the thread pools.
//创建java堆处理的线程池
heap_->CreateThreadPool();
// Reset the gc performance data at zygote fork so that the GCs
// before fork aren't attributed to an app.
//重置gc性能数据,以保证进程在创建之前的GCs不会计算到当前app上
heap_->ResetGcPerformanceInfo();

// We may want to collect profiling samples for system server, but we never want to JIT there.
if (is_system_server) {
jit_options_->SetUseJitCompilation(false);
jit_options_->SetSaveProfilingInfo(profile_system_server);
if (profile_system_server) {
jit_options_->SetWaitForJitNotificationsToSaveProfile(false);
VLOG(profiler) << "Enabling system server profiles";
}
}
if (!safe_mode_ &&
(jit_options_->UseJitCompilation() || jit_options_->GetSaveProfilingInfo()) &&
jit_ == nullptr) {
// Note that when running ART standalone (not zygote, nor zygote fork),
// the jit may have already been created.
//当flag1被设置,并且还没有创建JIT时,则创建JIT
CreateJit();
}
//设置信号处理函数
StartSignalCatcher();

// Start the JDWP thread. If the command-line debugger flags specified "suspend=y",
// this will pause the runtime (in the internal debugger implementation), so we probably want
// this to come last.
// 启动JDWP线程,当命令debuger的flags指定suspend=y时,则暂停runtime
ScopedObjectAccess soa(Thread::Current());
GetRuntimeCallbacks()->StartDebugger();
}

12. postForkCommon

[->ZygoteHooks.java]

1
2
3
4
5
6
7
8
9
public void postForkCommon() {
Daemons.startPostZygoteFork();
}
public static void startPostZygoteFork() {
ReferenceQueueDaemon.INSTANCE.startPostZygoteFork();
FinalizerDaemon.INSTANCE.startPostZygoteFork();
FinalizerWatchdogDaemon.INSTANCE.startPostZygoteFork();
HeapTaskDaemon.INSTANCE.startPostZygoteFork();
}

ZygoteHooks的postForkCommon主要功能是fork新进程后,启动zygote的四个Daemon线程,引用队列线程,析构线程,析构监控线程、java堆整理线程。

13. 小结

1.ZygoteInit.main方法,经过socket管道,预加载资源后,进入runSelectLoop方法。

2.runSelectLoop执行acceptCommandPeer,创建ZygoteConnection对象,并添加socketFDs数值,建立连接后,可以和客户端进行通信,进入processOneCommand方法接受客户端数据,并调用forkAndSpecialize方法创建进程。

3.forkAndSpecialize主要功能是

  • preFork:停止Zygote的4个Daemon线程的运行,初始化gc堆;

  • nativeForkAndSpecialize:调用fork创建新进程,设置新进程的主线程id,重置gc性能数据,设置信号处理函数等功能、启动JDWP线程。

  • postForkCommon:启动4个Daemon线程。

到此App进程完成创建的所有工作,执行forkAndSpecialize后,新创建的App进程进入了handleChildProc,后面就是App进程的工作了。

四、新进程运行

在第6小节中processOneCommand过程中调用forkAndSpecialize创建完新进程后,返回值pid=0即运行在子进程,继续开始执行handleChildProc方法。

14. ZC.handleChildProc

[->ZygoteConnection.java]

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
47
48
49
50
51
private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors,
FileDescriptor pipeFd, boolean isZygote) {
/**
* By the time we get here, the native code has closed the two actual Zygote
* socket connections, and substituted /dev/null in their place. The LocalSocket
* objects still need to be closed properly.
*/
//关闭zygote的socket的连接
closeSocket();
if (descriptors != null) {
try {
Os.dup2(descriptors[0], STDIN_FILENO);
Os.dup2(descriptors[1], STDOUT_FILENO);
Os.dup2(descriptors[2], STDERR_FILENO);

for (FileDescriptor fd: descriptors) {
IoUtils.closeQuietly(fd);
}
} catch (ErrnoException ex) {
Log.e(TAG, "Error reopening stdio", ex);
}
}

if (parsedArgs.mNiceName != null) {
//设置进程名
Process.setArgV0(parsedArgs.mNiceName);
}

// 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 {
//不是zygote进程
if (!isZygote) {
//执行目标类main方法,见流程15
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mRemainingArgs, null /* classLoader */);
} else {
return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mRemainingArgs, null /* classLoader */);
}
}
}

15. ZygoteInit.zygoteInit

[->ZygoteInit.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
//重定向log
RuntimeInit.redirectLogStreams();
//初始化,见流程15.1
RuntimeInit.commonInit();
//zygote初始化,见流程15.2
ZygoteInit.nativeZygoteInit();
//应用初始化
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}

15.1 commonInit

[-> RuntimeInit.java]

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
47
48
49
50
51
52
53
54
55
56
57
protected static final void commonInit() {
if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");

/*
* set handlers; these apply to all threads in the VM. Apps can replace
* the default handler, but not the pre handler.
*/
//设置默认的异常处理方法
LoggingHandler loggingHandler = new LoggingHandler();
RuntimeHooks.setUncaughtExceptionPreHandler(loggingHandler);
Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler));

/*
* Install a time zone supplier that uses the Android persistent time zone system property.
*/
//设置时区
RuntimeHooks.setTimeZoneIdSupplier(() -> SystemProperties.get("persist.sys.timezone"));

/*
* Sets handler for java.util.logging to use Android log facilities.
* The odd "new instance-and-then-throw-away" is a mirror of how
* the "java.util.logging.config.class" system property works. We
* can't use the system property here since the logger has almost
* certainly already been initialized.
*/
//重置log配置
LogManager.getLogManager().reset();
new AndroidConfig();

/*
* Sets the default HTTP User-Agent used by HttpURLConnection.
*/
//设置默认的HTTP User-Agent ,用于HttpURLConnection
String userAgent = getDefaultUserAgent();
System.setProperty("http.agent", userAgent);

/*
* Wire socket tagging to traffic stats.
*/
//设置socket的tag,用于流量统计
NetworkManagementSocketTagger.install();

/*
* If we're running in an emulator launched with "-trace", put the
* VM into emulator trace profiling mode so that the user can hit
* F9/F10 at any time to capture traces. This has performance
* consequences, so it's not something you want to do always.
*/
//配置trace
String trace = SystemProperties.get("ro.kernel.android.tracing");
if (trace.equals("1")) {
Slog.i(TAG, "NOTE: emulator trace profiling enabled");
Debug.enableEmulatorTraceOutput();
}

initialized = true;
}

15.2 nativeZygoteInit

[->AndroidRuntime.cpp]

1
2
3
4
5
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
//在AndroidRuntime.cpp中定义
gCurRuntime->onZygoteInit();
}

[->app_main.cpp]

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

ProcessState::self()主要工作是调用open打开dev/binder驱动设备,再利用mmap映射内核的地址空间,将Binder驱动的fd赋值给ProcessState对象中的mDriverFD,用于交互操作。

startThreadPool用于创建一个binder线程池,不断进行talkWithDriver。

15.3 applicationInit

[-> RuntimeInit.java]

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
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
// If the application calls System.exit(), terminate the process
// immediately without running any shutdown hooks. It is not possible to
// shutdown an Android application gracefully. Among other things, the
// Android runtime shutdown hooks close the Binder driver, which can cause
// leftover running threads to crash before the process actually exits.
//true代表应用程序退出时不调用AppRuntime.onExit,否则会在退出前退出
nativeSetExitWithoutCleanup(true);

// We want to be fairly aggressive about heap utilization, to avoid
// holding on to a lot of memory that isn't needed.
//设置虚拟机的内存利用率的参数为0.75
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);

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
//调用starClass的static方法,见流程16
return findStaticMain(args.startClass, args.startArgs, classLoader);
}

16. findStaticMain

[-> RuntimeInit.java]

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

/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
//通过抛出异常,回到zygoteInit.main方法,这样能清空栈帧,提高栈帧利用率,见流程17
return new MethodAndArgsCaller(m, argv);
}

MethodAndArgsCaller方法中的m是指main方法,argv是指ActivityThread,根据流程4可知,下一步进入到 caller.run()方法,也即MethodAndArgsCaller.run。

17. MethodAndArgsCaller

[-> RuntimeInit.java]

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
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静态方法,见流程18
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);
}
}
}

最后进入ActivityThread.main方法

18. AT.main

[->ActivityThread]

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
47
48
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");

// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);

Environment.initForCurrentUser();

// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);

Process.setArgV0("<pre-initialized>");
//创建主线程looper
Looper.prepareMainLooper();

// Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
// It will be in the format "seq=114"
long startSeq = 0;
if (args != null) {
for (int i = args.length - 1; i >= 0; --i) {
if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
startSeq = Long.parseLong(
args[i].substring(PROC_START_SEQ_IDENT.length()));
}
}
}
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);

if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}

if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}

// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//主线程进入循环状态
Looper.loop();

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

五、总结

Process.start方法是阻塞操作,直到进程创建完成并返回相应的进程pid时,才完成该方法。

app第一次启动时,其启动所在的进程会通过binder发送消息给Systemserver进程。systemserver进程是从Process.start开始,执行创建进程的操作。

Systemserver进程:通过Process.start方法发起创建新进程请求,会先收集各种新进程uid,gid,nice-name等相关参数,然后通过socket通道发送给zygote进程。

Zygote进程:接收到systemserver进程发送过来的参数后封装成Arguments对象,forAnddSpecialize方法是进程创建过程中最关键的一个过程,具体主要执行下面3个方法。

  • preFork:停止Zygote的4个Daemon线程(java堆内存整理线程,引用队列线程、析构线程以及监控线程)的运行,初始化gc堆;

  • nativeForkAndSpecialize:调用fork创建新进程,设置新进程的主线程id,创建java堆处理的线程池,重置gc性能数据,设置信号处理函数等功能、启动JDWP线程。

  • postForkCommon:启动之前被停止4个Daemon线程。

新进程:进入handleChildProc方法,设置进程名,打开binder驱动,启动新的binder线程,然后设置虚拟机参数,再通过调用目标类的main方法,即ActivityThread.main.

新进程由于会调用nativeZygoteInit,这个过程会调用startThreadPool创建binder线程池,所以每个进程一定至少包含一个Binder线程。

附录

源码路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
frameworks/base/core/java/android/os/ZygoteProcess.java
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
libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
art/runtime/native/dalvik_system_ZygoteHooks.cc
art/runtime/native/runtime.cc
frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
frameworks/base/cmds/app_process/app_main.cpp
bionic/libc/bionic/fork.cpp
art/runtime/signal_catcher.cc
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
frameworks/base/core/jni/AndroidRuntime.cpp
frameworks/base/core/java/android/app/ActivityThread.java