上篇文章《浅析Android系统启动过程》简要讲解了Android系统整体启动过程,今天我们看一下其中一个重要的过程:Zygote进程是如何启动的。

文中源码基于Android 8.0

概览

Zygote进程是通过init进程启动起来的,我们直接看Zygote进程的入口函数,位于ZygoteInit类中的main方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ZygoteInit {
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer();
//创建Socket
zygoteServer.registerServerSocket(socketName);

//预加载类和资源
preload(bootTimingsTraceLog);

//启动SystemServer进程
startSystemServer(abiList, socketName, zygoteServer);

//进入循环等待请求
zygoteServer.runSelectLoop(abiList);

由上面代码可以看出Zygote进程主要做了4件事:

  1. 创建一个Socket用于跨进程通信
  2. 预加载类和资源
  3. 启动SystemServer进程
  4. 进入循环等待AMS请求创建新的应用程序进程

我们继续跟进看看各个方法具体做了什么,

registerServerSocket

创建socket用于跨进程通信

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
void registerServerSocket(String socketName) {
if (mServerSocket == null) {
int fileDesc;
//拼接socket名称
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
//获取socket环境变量
String env = System.getenv(fullSocketName);
//将socket环境变量转换为fd文件描述符的参数
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
}

try {
//创建fd文件描述符
FileDescriptor fd = new FileDescriptor();
//设置fd参数
fd.setInt$(fileDesc);
//传入fd创建Socket
mServerSocket = new LocalServerSocket(fd);
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}

preload

预加载各种类及资源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static void preload(BootTimingsTraceLog bootTimingsTraceLog) {

//预加载/system/etc/preloaded-classes目录下常用的类
preloadClasses();

//预加载drawables、color、freeform_multi_window_drawables等常用资源
preloadResources();

//预加载OpenGL
preloadOpenGL();

//预加载android、compiler_rt、jnigraphics库
preloadSharedLibraries();

//预加载字体资源
preloadTextResources();

}

startSystemServer

启动SystemServer进程

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
private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
throws Zygote.MethodAndArgsCaller, RuntimeException {
long capabilities = posixCapabilitiesAsBits(
OsConstants.CAP_IPC_LOCK,
OsConstants.CAP_KILL,
OsConstants.CAP_NET_ADMIN,
OsConstants.CAP_NET_BIND_SERVICE,
OsConstants.CAP_NET_BROADCAST,
OsConstants.CAP_NET_RAW,
OsConstants.CAP_SYS_MODULE,
OsConstants.CAP_SYS_NICE,
OsConstants.CAP_SYS_PTRACE,
OsConstants.CAP_SYS_TIME,
OsConstants.CAP_SYS_TTY_CONFIG,
OsConstants.CAP_WAKE_ALARM
);
/* Containers run without this capability, so avoid setting it in that case */
if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
}
/* Hardcoded command line to start the system server */


String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"com.android.server.SystemServer",
};//---1---
ZygoteConnection.Arguments parsedArgs = null;

int pid;

try {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);//---2---
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}

/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}

zygoteServer.closeServerSocket();
handleSystemServerProcess(parsedArgs);//---3---
}

return true;
}

注释1处创建args数组,用来保存用于启动SystemServer进程的启动参数。注释2处调用Zygote.forkSystemServer方法,通过fork当前进程来创建SystemServer进程,如果进程的pid值为0,则表示当前运行在新创建的进程中,就会执行注释3处的handleSystemServerProcess来处理SystemServer进程。关于SystemServer进程的启动放在之后的文章讲解。

runSelectLoop

死循环等待AMS请求

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
void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

//---1---
fds.add(mServerSocket.getFileDescriptor());
peers.add(null);

while (true) {
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) {//---2---
pollFds[i] = new StructPollfd();
pollFds[i].fd = fds.get(i);
pollFds[i].events = (short) POLLIN;
}
try {
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
for (int i = pollFds.length - 1; i >= 0; --i) {//---3---
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);//---4---
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done = peers.get(i).runOnce(this);//---5---
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}

注释1处获取之前创建的socketfd添加到fds中,然后进入无限循环来等待AMS请求Zygote进程创建新的应用程序进程。注释2处遍历fds存储的信息放到pollFds中。注释3处对pollFds进行遍历,如果i=0说明pollFds中没有内容,此时会通过注释4处acceptCommandPeer方法创建一个ZygoteConnection,然后获取ZygoteConnectionfd并加入到fds中,以便接收下次AMS的请求。而当i!=0时,会执行注释5处的peers.get(i).runOnce(this),这个方法用来处理AMS发送过来的请求,处理完后,将ZygoteConnectionpeers中移除,将fdfds中移除,并进入下次循环。

关注我