1.Zygote
Zygote译为“受精卵”,是Android中SystemServer和几乎所有Java应用的孵化器。SystemServer和Java应用的父进程都是zygote。zygote是一个很重要的服务进程,没有zygote就没有Android,Android的启动也离不开zygote。
zygote的作用:
zygote作为Android的虚拟机,最主要的作用就是启动SystemServer进程和fork新的应用进程。
zygote的启动:
zygote是服务进程的别名,zygote是由rc文件定义init启动的服务。从rc文件中可以看出:
①zygote的进程优先级是最高的,priority被设成-20,主要是因为Android的启动非常依赖于SystemServer的启动,而SystemServer也是zygote fork出来的,因此需要将zygote优先级设成最高的。
②zygote在启动时创建了两个socket(zygote和usap_pool_primary),用于进程间的通信。
③zygote是Android非常重要的核心服务之一,当其因异常退出后,init会将其重新启动,并将一些相关的节点和服务重新设置。
zygote的启动实际上分成了两部分:SystemServer的启动、ZygoteServer的启动。两者前面是在同一个进程中执行的,当虚拟机创建完成后才正式分离。
zygote启动的前奏:
#frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[]) {
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
…
runtime.start( "com.android.internal.os.ZygoteInit", args, zygote);
…
}
创建AppRuntime,并执行Java代码ZygoteInit类的main方法:
public static void main(String argv[]) { //已简化
ZygoteServer zygoteServer = null;
Runnable caller;
Zygote.initNativeState(isPrimaryZygote);
zygoteServer = new ZygoteServer( isPrimaryZygote);
……
preload(bootTimingsTraceLog);
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
if (r != null) {
r.run();
return;
}
}
caller = zygoteServer.runSelectLoop(abiList);
if (caller != null) {
caller.run();
}
}
ZygoteInit的main()方法是Android启动中的第一个Java进程的主方法。在ZygoteInit中,一般无特殊原因,都会调用preload()方法将Android Java层应用常用的资源预加装,其原因是:
①Android是基于Linux系统开发的,底层就是Linux操作系统,而Linux进程的fork机制有一个特点,就是写时拷贝机制,即fork出来的进程最初是共用一块内存,只有当发生写操作时,才会将对应的内存块进行拷贝修改,而一些只读的内存块则会所有fork出来的进程共享。
②preload()方法所加装的东西主要有以下几类:常用类文件、Resources资源、HALs资源、opengl、webview等。这些资源一般都是只读的,不会进行修改,而且是很多应用都可能会用到的。因此预先加载后所有由zygote fork出来的应用进程都能共用一块内存。
zygote启动时进行preload的作用是什么?zygote作为Android的虚拟机,很多应用(java/kotlin)的资源都是共用的,zygote利用了Linux操作系统的copy-on-write机制,预先加载了常用的资源,然后其他的应用通过fork后,所有的进程都能共享一份只能的资源,而不需要为每个应用进程都单独加载一份。
启动SystemServer:
SystemServer是通过forkSystemServer()方法fork出来并开始执行。
private static Runnable forkSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) {
ZygoteArguments parsedArgs = null;
int pid;
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();
return handleSystemServerProcess( parsedArgs);
}
return null;
}
forkSystemServer()中主要做了两件事:①调用Zygote.forkSystemServer()方法去fork一个新的进程出来。②fork()后的子进程是SystemServer进程,则等待zygote的启动完成,并执行真正的SystemServer代码。
// Zygote.java
public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
ZygoteHooks.preFork();
// Resets nice priority for zygote process.
resetNicePriority();
int pid = nativeForkSystemServer( uid, gid, gids, runtimeFlags, rlimits, permittedCapabilities, effectiveCapabilities);
// Enable tracing as soon as we enter the system_server.
if (pid == 0) {
Trace.setTracingEnabled(true, runtimeFlags);
}
ZygoteHooks.postForkCommon();
return pid;
}
ZygoteHooks.preFork():将Daemons线程关掉,虚拟机进行一些copy前的处理。
resetNicePriority():将进程的优先级设回普通的级别。
nativeForkSystemServer():调用native层方法去fork一个新的进程。该方法主要调用Linux的fork系统调用,fork一个新的进程,子进程的pid为0,父进程返回子进程的pid值。
ZygoteHooks.postForkCommon():重新启动Daemons线程,虚拟机进行copy后的处理。
fork操作是不会将进程中所有线程拷贝的,只会拷贝当前线程。
Daemons线程是指:①HeapTaskDaemon;②ReferenceQueueDaemon;③FinalizerDaemon;④FinalizerWatchdogDaemon。平时在trace文件(ANR或者其他方式获取的trace文件)中看到Java应用进程都会有这4个线程,这4个线程就是在这里创建的。
再回到ZygoteInit.forkSystemServer()方法,此时两个进程都会返回到此处,然后两个进程到这就分道扬镳了。SystemServer进程将ZygoteServer的socket关闭,然后调用handleSystemServerProcess()方法去执行SystemServer的源码。
handleSystemServerProcess()方法的核心代码:
createSystemServerClassLoader();
ClassLoader cl = sCachedSystemServerClassLoader;
if (cl != null) {
Thread.currentThread().setContextClassLoa der(cl);
}
return ZygoteInit.zygoteInit( parsedArgs.mTargetSdkVersion,parsedArgs.mRemainingArgs, cl);
先获取classloader,并将其设置为root classloader。然后调用ZygoteInit.zygoteInit()方法去执行。
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
RuntimeInit.commonInit();
ZygoteInit.nativeZygoteInit();
return RuntimeInit.applicationInit( targetSdkVersion, argv, classLoader);
}
ZygoteInit.nativeZygoteInit()方法为进程创建Binder的环境(ProcessStatae)。
RuntimeInit.applicationInit()方法则会去执行传参进来的类的main()方法,这里就是:com.android.server.SystemServer。
ZygoteInit.forkSystemServer()返回一个runnable,返回到ZygoteInit.main()方法后,SystemServer进程就会继续执行这个runnable。
zygote在fork进程后,使用runnable的方式返回到main()方法后才执行的原因?减少线程堆栈的长度,因为fork后进行执行的内容与之前zygote的堆栈内容并无关系,因此不需要为每个进程都保留前面的堆栈信息,而且还能减少进程的堆栈容量限制。
ZygoteServer.runSelectLoop:
当zygote进程返回到main()方法后,就会继续执行ZygoteServer.runSelectLoop()方法,从名字和注释来看,这个方法应该是一个死循环,是不断进行循环执行命令的方法。
runSelectLoop()方法主要做两件事:
①每次循环都重新构建监听文件列表,主要是ZygoteServer的socket文件(ZygoteServer的socket和其他应用进程连接过来的socket)和usap文件节点。
②监听文件列表,并从中获取命令执行。
一张图看看Zygote的启动流程: