(注:以下代码分析基于android-10.0.0_r30)
一 概述
之前介绍了关于Zygote的启动过程,这一篇再来详细说说Zygote的工作原理
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
frameworks/base/core/java/android/net/LocalServerSocket.java
frameworks/base/core/java/android/net/LocalSocket.java
frameworks/base/core/java/com/android/internal/os/Zygote.java
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
二 ZygoteInit
Zygote工作的入口,是在ZygoteInit中的几行代码开启的
[ZygoteInit.java]
Runnable caller;
//创建一个ZygoteServer,传入的是一个boolean变量
zygoteServer = new ZygoteServer(isPrimaryZygote);
//通过zygoteServer获取一个run对象
caller = zygoteServer.runSelectLoop(abiList);
...
if (caller != null) {
//开始loop循环
caller.run();
}
三 ZygoteServer.java
3.1 ZygoteServer的构造函数
[ZygoteServer.java]
ZygoteServer(boolean isPrimaryZygote) {
//获取一个UsapPoolEventFD,这个fd是用ZygoteServer轮询的
mUsapPoolEventFD = Zygote.getUsapPoolEventFD();
if (isPrimaryZygote) {
//创建一个mZygoteSocket,这个ZygoteSocket其实是LocalServerSocket
//在LocalServerSocket里面有一个实现类LocalSocketImpl,在这个创建方法里面会创建一个fd
//之后的轮询里面会用到这个fd
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
//创建一个UsapPoolSocket
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
} else {
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
}
fetchUsapPoolPolicyProps();
mUsapPoolSupported = true;
}
在ZygoteServer的构造函数里面,会创建一个ZygoteSocket,它其实是一个LocalServerSocket,这个类里面有一个对应的实现类LocalSocketImpl和一个fd,因为在Android中,Zygote和AMS的通信使用的是sock而不是binder,而socket又是C/S架构的,所以此时作为Server端的ZygoteServer,持有的是一个LocalServerSocket,如果Client端想要通信,那么就需要使用对应的Client端的LocalSocket
3.2 runSelectLoop
runSelectLoop这个方法较长,虽然用于处理Client的socket消息,但是因为引入了UsapPool,所以有很多UsapPool的相关逻辑,不过在runSelectLoop中,最主要的处理逻辑,都是通过ZygoteConnection来完成的
[ZygoteServer.java]
Runnable runSelectLoop(String abiList) {
//创建两个数组
//数组socketFDs里面存放的是一些fd,用来做socket通信的
//数组peers里面存放的是ZygoteConnection
ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
//第0位添加一个从ZygoteSocket获取的fd
socketFDs.add(mZygoteSocket.getFileDescriptor());
peers.add(null);
while (true) {
//这前面的一大段逻辑都是处理UsapPool相关的
//并且会将socketFDs进行一些处理,构造出一个structs poll的结构体,然后通过USAP连接池进行处理
//根据Zygote的USAP池的状态有不同的Zygote(可以是常规Zygote,WebView Zygote或AppZygote)。
...
try {
//等待事件socket的fd事件
Os.poll(pollFDs, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
boolean usapPoolFDRead = false;
while (--pollIndex >= 0) {
if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
continue;
}
if (pollIndex == 0) {
// ZygoteSocket收到请求,通过acceptCommandPeer创建一个ZygoteConnection
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
socketFDs.add(newPeer.getFileDescriptor());
} else if (pollIndex < usapPoolEventFDIndex) {
// Session socket accepted from the Zygote server socket
try {
ZygoteConnection connection = peers.get(pollIndex);
//处理socket消息
final Runnable command = connection.processOneCommand(this);
//在Child端
if (mIsForkChild) {
if (command == null) {
throw new IllegalStateException("command == null");
}
return command;
} else {
//在Server端
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) {
//在server端,因此这里发生的任何异常之前都是
//在处理命令或从读写socket。 对此做一个提醒以便
//确切知道失败的原因。
// 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);
//关闭socket避免超时
ZygoteConnection conn = peers.remove(pollIndex);
conn.closeSocket();
socketFDs.remove(pollIndex);
} else {
//在child端,异常发生在ActivityThread.main之前
Log.e(TAG, "Caught post-fork exception in child process.", e);
throw e;
}
} finally {
//重置child的标志,在Runnable之后不在使用
mIsForkChild = false;
}
} else {
// USAP池事件FD或USAP报告管道。
//如果这是USAP池事件FD,则有效负载将是已删除的USAP的数量。
//如果这是USAP报告管道FD,则有效负载将是USAP的PID
//这只是专门的。
long messagePayload = -1;
try {
byte[] buffer = new byte[Zygote.USAP_MANAGEMENT_MESSAGE_BYTES];
int readBytes = Os.read(pollFDs[pollIndex].fd, buffer, 0, buffer.length);
if (readBytes == Zygote.USAP_MANAGEMENT_MESSAGE_BYTES) {
DataInputStream inputStream =
new DataInputStream(new ByteArrayInputStream(buffer));
messagePayload = inputStream.readLong();
} else {
Log.e(TAG, "Incomplete read from USAP management FD of size "
+ readBytes);
continue;
}
} catch (Exception ex) {
if (pollIndex == usapPoolEventFDIndex) {
Log.e(TAG, "Failed to read from USAP pool event FD: "
+ ex.getMessage());
} else {
Log.e(TAG, "Failed to read from USAP reporting pipe: "
+ ex.getMessage());
}
continue;
}
if (pollIndex > usapPoolEventFDIndex) {
Zygote.removeUsapTableEntry((int) messagePayload);
}
usapPoolFDRead = true;
}
}
//检查USAP池是否需要重新填充
if (usapPoolFDRead) {
int[] sessionSocketRawFDs =
socketFDs.subList(1, socketFDs.size())
.stream()
.mapToInt(fd -> fd.getInt$())
.toArray();
final Runnable command = fillUsapPool(sessionSocketRawFDs);
if (command != null) {
return command;
}
}
}
}
3.3 acceptCommandPeer
[ZygoteServer.java]
private ZygoteConnection acceptCommandPeer(String abiList) {
try {
//这个socket是server端的socket,通过accept来接受client传递的数据
return createNewConnection(mZygoteSocket.accept(), abiList);
} catch (IOException ex) {
throw new RuntimeException(
"IOException during accept()", ex);
}
}
3.4 createNewConnection
[ZygoteServer.java]
protected ZygoteConnection createNewConnection(LocalSocket socket, String abiList)
throws IOException {
return new ZygoteConnection(socket, abiList);
}
4 ZygoteConnection
4.1 processOneCommand
在之前的ZygoteServer中,创建ZygoteConnection对象,并创建了LocalServerSocket,现在接收到Client端发送来的数据,就会通过processOneCommand来进行处理,这里的处理方法也比较简单,就是读出参数,解析参数,校验,然后fork子进程,最后分别处理父进程和子进程的逻辑
[ZygoteConnection.java]
Runnable processOneCommand(ZygoteServer zygoteServer) {
String args[];
ZygoteArguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
//获取Client发送的参数
args = Zygote.readArgumentList(mSocketReader);
descriptors = mSocket.getAncillaryFileDescriptors();
} ...
//解析参数
parsedArgs = new ZygoteArguments(args);
//拿到参数后一系列的校验工作
...
//校验完毕,通过参数fork出一个子进程
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) {
//在子进程,处理子进程的相关逻辑
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
return handleChildProc(parsedArgs, descriptors, childPipeFd,
parsedArgs.mStartChildZygote);
} else {
//在父进程(Zygote进程),处理父进程的相关逻辑
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
handleParentProc(pid, descriptors, serverPipeFd);
return null;
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
现在子进程也创建完毕了,接下来再看看关于父进程的处理逻辑handleParentProc和子进程的处理逻辑handleChildProc又做了什么
4.2 handleChildProc
[ZygoteConnection.java]
private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors,
FileDescriptor pipeFd, boolean isZygote) {
//子进程会从父进程继承socket,这里进行关闭
closeSocket();
...
if (!isZygote) {
//不是zygote进程,所以走这个分支
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mRemainingArgs, null /* classLoader */);
} else {
return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mRemainingArgs, null /* classLoader */);
}
}
}
4.3 zygoteInit
关于zygoteInit这个方法,它主要做了三件事
- RuntimeInit.commonInit()
- ZygoteInit.nativeZygoteInit()
- RuntimeInit.applicationInit
这三个方法主要做了一些初始化的操作,在之后的进程启动时会详细介绍,
[ZygoteInit.java]
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");
RuntimeInit.redirectLogStreams();
RuntimeInit.commonInit();
ZygoteInit.nativeZygoteInit();
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
4.4 RuntimeInit.applicationInit
applicationInit这个方法也比较简单,其中最关键是就是最后一行的findStaticMain
[RuntimeInit.java]
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
...
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
4.5 findStaticMain
[RuntimeInit.java]
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
...
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch ...
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
...
}
return new MethodAndArgsCaller(m, argv);
}
4.6 MethodAndArgsCaller
static class MethodAndArgsCaller implements Runnable {
...
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
} ...
}
}
五 总结
显然,applicationInit是通过jni的反射获得到一个Java的main方法的Runnable,它实际上就是ActivityThread的main方法,然后最后通过最外层的run来执行这个main方法,这样我们应用的进程就启动了,相对的,在对应的父进程中,zygote会处理一些扫尾工作,等待下一次的fork,到这,关于zygote的工作流程也算是基本告一段落了,当然,关于系统的启动,还远远没有结束,这些在接下来的篇幅说明