我正在参加中秋创意投稿大赛,详情请看:中秋创意投稿大赛
Android Zygote启动(AOSP 11)
AndroidRuntime.start:
接上文 Android Init启动 ,我们知道了init进程启动完成之后,会通过AndroidRuntime.start方法,加载ZygoteInit这个Java类,进行Zygote进程的启动。
Zygote的中文释义是【受精卵】,通常也叫做孵化器,是一个很贴切的名字,Android中的App应用进程以及系统关键服务进程SystemServer进程,都是通过Zygote进程进行创建的。
而Zygote进程在启动的时候,会创建一个AndroidRuntime,当通过fork调用创建一个子进程的时候,子进程便也有了一个AndroidRuntime。
ART.start最主要的作用就是通过调用指定ClassName的static void main方法,启动一个JVM:
// 第一个参数是className(非simpleName),第二个参数是要传给main的参数
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
// ...
static const String8 startSystemServer("start-system-server");
// Whether this is the primary zygote, meaning the zygote which will fork system server.
bool primary_zygote = false;
// 启动参数包含了start-system-server,就表示启动的是Zygote主模式
for (size_t i = 0; i < options.size(); ++i) {
if (options[i] == startSystemServer) {
primary_zygote = true;
/* track our progress through the boot sequence */
const int LOG_BOOT_PROGRESS_START = 3000;
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
}
}
// ...
// 省略一些环境参数的设置
// ...
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
// startVm中通过各种参数的配置,最终调用到JNI_CreateJavaVM,创建一个JVM实例
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
return;
}
onVmCreated(env);
// 将各种Android相关的JNI函数注册到JVM中,比如Log,Binder等等
// 具体可以看base/core/jni/AndroidRuntime.cpp中的代码
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
// 把各种要传给main方法的参数封装好
// 准备启动JVM了
// 把启动的className的'.'替换为'/'
char* slashClassName = toSlashClassName(className != NULL ? className : "");
// 找到要启动的Class
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
// 找到要启动的Class的main方法
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
// 执行要启动的Class的main方法
env->CallStaticVoidMethod(startClass, startMeth, strArray);
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
// 程序正常运行是不会走到这里的
// ...
}
复制代码
所以ART.start做的核心事情就是:
- 启动一个JVM。
- 将android提供的JNI注册到启动的JVM中。
- 找到ZygoteInit这个class并执行它的main函数。
至此,Zygote的启动就从Native Framework转移到了Java Framework。
ZygoteInit:
在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java中:
public static void main(String[] argv) {
// ...
try {
// ...
boolean startSystemServer = false;
String zygoteSocketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
// 需要启动SystemServer
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)) {
// 获取zygote进程的socket的name
zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
if (!enableLazyPreload) {
// 预加载类和资源
preload(bootTimingsTraceLog);
}
// ①核心,创建ZygoteServer对象。
zygoteServer = new ZygoteServer(isPrimaryZygote);
if (startSystemServer) {
// ②核心,fork出SystemServer
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
if (r != null) {
r.run();
return;
}
}
// ③核心,开启Zygote的select循环
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}
if (caller != null) {
caller.run();
}
}
复制代码
创建ZygoteServer对象如下:
ZygoteServer(boolean isPrimaryZygote) {
mUsapPoolEventFD = Zygote.getUsapPoolEventFD();
if (isPrimaryZygote) {
// 如果是主Zygote进程,那么会创建socket,socket的名字为ANDROID_SOCKET_zygote
// 同时socket监听的最大连接数量为50
// frameworks/base/core/java/android/net/LocalServerSocket.java
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
} else {
// 如果是辅助Zygote进程,也是一样的
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
}
mUsapPoolSupported = true;
// 配置USAP相关属性,USAP是Android 10引入的新机制
// 通过提前fork出一批进程的方式,当有新进程需要创建的时候
// 直接将提前创建好的进程进行分配,省去了临时fork,以提高性能表现。
fetchUsapPoolPolicyProps();
}
// Zygote.createManagedSocketFromInitSocket
static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
// 得到socket的环境变量的值
String env = System.getenv(fullSocketName);
// 转换环境变量为文件描述符参数
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
}
try {
// 创建Socket对应的文件描述符
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
// 创建LocalServerSocket对象
return new LocalServerSocket(fd);
} catch (IOException ex) {
throw new RuntimeException(
"Error building socket from file descriptor: " + fileDesc, ex);
}
}
// impl.listen中会开启监听这个fd
// AMS和Zygote通信是基于Socket的,后续AMS可以通过这个socket
// 与Zygote进行通信。
public LocalServerSocket(FileDescriptor fd) throws IOException
{
impl = new LocalSocketImpl(fd);
impl.listen(LISTEN_BACKLOG);
localAddress = impl.getSockAddress();
}
复制代码
创建并完成了Zygote作为Socket Server端Socket相关设置工作,接着看到②处的forkSystemServer:
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
// 省略:一些配置SystemServer的启动参数,
// 包含比如启动类名为com.android.server.SystemServer
int pid;
try {
// fork创建SystemServer进程
pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
// pid==0表示是子进程,zygote进程的子进程即SystemServer进程
if (pid == 0) {
// 如果需要辅助模式的zygote进程,那么会为辅助zygote进程同样创建socket连接
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
// 因为SystemServer进程fork自Zygote进程,自然也复制了包括Zygote的socket连接
// 但是这些连接对于SystemServer是没有作用的,因此需要关闭。
zygoteServer.closeServerSocket();
// 处理SystemServer进程
return handleSystemServerProcess(parsedArgs);
}
return null;
}
复制代码
上面代码中,核心是Zygote.forkSystemServer,通过nativeForkSystemServer这个native调用,完成SystemServer进程的创建。nativeForkSystemServer的实现位于base/core/jni/com_android_internal_os_zygote.cpp中,核心实现就是ForkCommon中通过fork调用,创建一个进程,同时,也会做一些系统信号Handler设置工作。fork出了SystemServer进程后,在handleSystemServerProcess往后的一系列调用中,最终会找到SystemServer的Class和main方法,启动SystemServer。
继续回到ZygoteInit中:
// ③核心,开启Zygote的select循环
caller = zygoteServer.runSelectLoop(abiList);
复制代码
runSelectLoop的实现如下:
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> socketFDs = new ArrayList<>();
// 与Zygote进程建立的链接
ArrayList<ZygoteConnection> peers = new ArrayList<>();
// 将Zygote进程创建的Socket(即下文提到的PRIMARY_SOCKET_NAME)
// 添加到socketFDs中
socketFDs.add(mZygoteSocket.getFileDescriptor());
peers.add(null);
mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
// 无限循环
while (true) {
// ...
int[] usapPipeFDs = null;
StructPollfd[] pollFDs;
// 将socetFD存储的信息保存到StructPollfd
int pollIndex = 0;
for (FileDescriptor socketFD : socketFDs) {
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = socketFD;
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
}
// ...
// 等待pollFDs对应的Socket中有数据写入
try {
pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
// ...
if (pollReturnValue == 0) {
// 省略
} else {
boolean usapPoolFDRead = false;
while (--pollIndex >= 0) {
if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
continue;
}
if (pollIndex == 0) {
// pollIndex为0,则表示有进程与Zygote Socket建立连接(比如AMS),
// 会创建一个ZygoteConnection添加到Zygote Socket的连接池中
// 而connetion关联的socket就是
// Zygete启动过过程中创建的名字为PRIMARY_SOCKET_NAME的
// mZygoteSocket
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
// 将ZygeteConnection的FD添加到socketFDs中,那么后面Zygote便可以
// 接收到AMS发送的请求。
socketFDs.add(newPeer.getFileDescriptor());
} else if (pollIndex < usapPoolEventFDIndex) {
// pollIndex不为0,则表示比如AMS向Zygote发送了请求
// 同时,可以通过USAP机制创建进程
try {
ZygoteConnection connection = peers.get(pollIndex);
boolean multipleForksOK = !isUsapPoolEnabled()
&& ZygoteHooks.isIndefiniteThreadSuspensionSafe();
// 内部调用Zygote的forkSimpleApp进行应用进程的创建
final Runnable command =
connection.processCommand(this, multipleForksOK);
}
// ...
}
复制代码
回看startViaZygote:
之前在 Activity启动流程分析 中,我们知道了App新进程的创建,最终是通过ZygoteProcess.startViaZygote调用完成的。现在就来看看,这个function后面坐了哪些事情:
startViaZygote如下:
// ...
// 一大堆根据入参,进行参数组装的逻辑
// 最后
synchronized(mLock) {
// The USAP pool can not be used if the application will not use the systems graphics
// driver. If that driver is requested use the Zygote application start path.
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
zygotePolicyFlags,
argsForZygote);
}
复制代码
zygoteSendArgsAndGetResult->attemptZygoteSendArgsAndGetResult,在zygoteSendArgsAndGetResult中会将启动参数处理成一个string,传递给attemptZygoteSendArgsAndGetResult
private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(
ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {
try {
final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;
// 将要启动进程的各种信息,写入到zygoteWriter的buffer中。
zygoteWriter.write(msgStr);
// 刷新buffer
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();
Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "
+ ex.toString());
throw new ZygoteStartFailedEx(ex);
}
}
复制代码
BufferedWriter 和 BufferedReader是带有缓冲的字符输入输出流,write的时候,将信息写入Buffer中,flush的时候,将缓冲区的数据写入到目的文件。因此我们得知道mZygoteOutputWriter到底是在往哪里写数据,
mZygoteOutputWriter是在ZygoteState对象创建的时候赋值的:
private ZygoteState(LocalSocketAddress zygoteSocketAddress,
LocalSocketAddress usapSocketAddress,
LocalSocket zygoteSessionSocket,
DataInputStream zygoteInputStream,
BufferedWriter zygoteOutputWriter,
List<String> abiList) {
this.mZygoteSocketAddress = zygoteSocketAddress;
this.mUsapSocketAddress = usapSocketAddress;
this.mZygoteSessionSocket = zygoteSessionSocket;
this.mZygoteInputStream = zygoteInputStream;
this.mZygoteOutputWriter = zygoteOutputWriter;
this.mAbiList = abiList;
}
复制代码
ZygoteState的创建是在ZygoteState的connect方法中:
static ZygoteState connect(@NonNull LocalSocketAddress zygoteSocketAddress,
@Nullable LocalSocketAddress usapSocketAddress)
throws IOException {
DataInputStream zygoteInputStream;
BufferedWriter zygoteOutputWriter;
// 创建一个LocalSocket对象
final LocalSocket zygoteSessionSocket = new LocalSocket();
if (zygoteSocketAddress == null) {
throw new IllegalArgumentException("zygoteSocketAddress can't be null");
}
try {
// 将LocalSocket对象连接到zygoteSocketAddress中
// 与server端的socket建立连接
// 底层是通过zygoteSocketAddress对应的Socket的fd建立连接
zygoteSessionSocket.connect(zygoteSocketAddress);
zygoteInputStream = new DataInputStream(zygoteSessionSocket.getInputStream());
// zygoteOutputWriter写入的就是zygoteSessionSocket的输出流中。
zygoteOutputWriter =
new BufferedWriter(
new OutputStreamWriter(zygoteSessionSocket.getOutputStream()),
Zygote.SOCKET_BUFFER_SIZE);
} catch (IOException ex) {
try {
zygoteSessionSocket.close();
} catch (IOException ignore) { }
throw ex;
}
return new ZygoteState(zygoteSocketAddress, usapSocketAddress,
zygoteSessionSocket, zygoteInputStream, zygoteOutputWriter,
getAbiList(zygoteOutputWriter, zygoteInputStream));
}
复制代码
那么我们知道了,最终mZygoteOutputWriter写入的数据将被zygoteSocketAddress对应的Socket端读取到,而zygoteSocketAddress对于64位主模式而言,是ZygoteProcess中的mZygoteSocketAddress,在ZygoteProcess的构造方法中:
mZygoteSocketAddress =
new LocalSocketAddress(Zygote.PRIMARY_SOCKET_NAME,
LocalSocketAddress.Namespace.RESERVED);
复制代码
PRIMARY_SOCKET_NAME就是”zygote”
那么PRIMARY_SOCKET_NAME这个Socket的读取是在什么时候进行的呢?回到ZygoteInit的runSelectLoop中,在其它进程比如AMS与Zygote建立连接的时候,实际上已经关联上了PRIMARY_SOCKET_NAME这个Zygote启动过程中创建的ZygoteServer对象持有的Socket对象。那么后续写入的数据,而Zygote的runSelectloop中,poll机制观察的一堆Socket的fd中,就包含了PRIMARY_SOCKET_NAME。
当有请求进程创建的数据写入到PRIMARY_SOCKET_NAME这个Socket中的时候,runSelectloop中的无限循环就会被唤醒,然后调用connection.processCommand,在其中,如果是App进程的创建,会调用到Zygote的forkSimpleApps,然后再最终通过zygote::forkApp -> zygote::ForkCommon,而ForkCommon上面也提到了,fork出一个子进程,这样,子进程就算是创建出来了,然后Zygote在把子进程的一些配置搞一搞,一个新的App进程就算是创建完成了。