Zygote简介
zygote是Android一个非常重要的进程,和init、systemServer进程这三个进程是Android系统非常重要的进程。
Linux的进程是通过fork产生,fork出来的进程除了一些核心数据结构和父进程不一样,其余的内存映像都是和父进程共享的。通常子进程fork出来后,会继续执行exec。exec将用一个新的可执行文件的内容替代当前进程的代码段、数据段、堆和栈。init进程启动各种service就是这样的。
Zygote创建应用却只用了fork,没有调用exec。Android应用执行的是java代码,java代码的不同才造成了应用的区别,而对于java的环境要求却是一样的。
Zygote初始化会创建虚拟机、同时把需要的系统类库和资源文件加载到内存里。zygote fork出子进程后,子进程也继承了能正常工作的虚拟机的各种系统资源,接下来子进程只需要装载apk文件中的字节码就可以运行了。
在init.rc 中zygote是通过import /init.${ro.zygote}.rc引入的,有32位、64位之分,我们主要看下32位的。
zygote是属于class main的当zygote重新启动 audioserver等一些service也会重启。
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
app_process
app_process的main函数
这个函数主要就是解析启动参数。app_process除了能创建Zygote进程外、还能创建普通进程。我们从init.rc中传入的参数:
-Xzygote /system/bin --zygote --start-system-server。
最后niceName是zygote、startSystemServer是true zygote是true。
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
++i; // Skip unused "parent dir" argument.
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
如果启动参数有--zygote执行ZygoteInit类,否则执行通过参数传进来的Java类。
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
}
app_process除了能启动Zygote进程,也可以使用它来执行系统的某个java类,比如am命令。
AndroidRuntime
AndroidRuntime一个Android底层的一个类,负责启动虚拟机java线程。AndroidRuntime类在一个进程中只有一个实例对象。
前面在app_process的main函数中最后调用了AndroidRuntime的start函数。这个函数主要启动虚拟机,然后通过CallStaticVoidMethod函数来调用java层的函数。这样Zygote的初始化过程转到了java层了。当然如果启动的不是Zygote而是执行的java类将是调用RuntimeInit函数。
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
ALOGD(">>>>>> START %s uid %d <<<<<<\n",
className != NULL ? className : "(unknown)", getuid());
static const String8 startSystemServer("start-system-server");
/*
* 'startSystemServer == true' means runtime is obsolete and not run from
* init.rc anymore, so we print out the boot start event here.
*/
for (size_t i = 0; i < options.size(); ++i) {
if (options[i] == startSystemServer) {
/* 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)));
}
}
const char* rootDir = getenv("ANDROID_ROOT");
if (rootDir == NULL) {
rootDir = "/system";
if (!hasDir("/system")) {
LOG_FATAL("No root directory specified, and /android does not exist.");
return;
}
setenv("ANDROID_ROOT", rootDir, 1);
}
//const char* kernelHack = getenv("LD_ASSUME_KERNEL");
//ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
/*
* Register android functions.
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
......
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
char* slashClassName = toSlashClassName(className != NULL ? className : "");
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
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 {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
}
ZygoteInit
ZygoteInit类负责Zygote进程java层的初始化工作。这个类的main函数主要注册了zygote的socket来监听应用程序的启动消息,加载资源、启动systemserver、然后进入socket监听等。我们需要注意这个函数已经fork了一个system_server并且zygote主线程最后在执行runSelectLoop函数监听其他应用进程启动的消息。当有启动进程的socket消息,runSelectLoop函数就会返回,当然这个时候返回是在子进程中,zygote进程还是不听监控socket,最后通过返回的caller,然后执行器run函数。这样就到应用进程的ActivityThread的main函数了。
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer();
......
final Runnable caller;
try {
......
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.");
}
zygoteServer.registerServerSocket(socketName);//注册socket监听,用来接收启动应用启动的消息
// In some configurations, we avoid preloading resources and classes eagerly.
// In such cases, we will preload things prior to our first fork.
if (!enableLazyPreload) {
preload(bootTimingsTraceLog);//加载资源
} 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 process unmounts root storage spaces.
Zygote.nativeUnmountStorageOnInit();
// Set seccomp policy
Seccomp.setPolicy();
ZygoteHooks.stopZygoteNoThreadCreation();
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);//启动systemserver进程
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}
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);//监听socket消息,并且获取到java的函数入口,这里zygote会一直循环,能返回的都是fork出来的子进程
} 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();//这个时候在子进程中,一般调用ActivityThread的main方法了
}
}
请求启动应用进程
Android启动一个新的进程都是在AMS中通过其startProcessLocked函数来完成,这个我们在之前分析AMS的博客分析过了。
这个函数最后会调用如下代码,而这个entryPoint就是android.app.ActivityThread
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, entryPointArgs);
而最后是调用了ZygotePrcocess的startViaZygote函数,这个函数又调用了zygoteSendArgsAndGetResult函数,而zygoteSendArgsAndGetResult这个函数把会这些参数通过socket传给zygote,而我们现在的进程就是system_server。
然后我们再来看zygote进程的ZygoteInit类中main方法调用的runSelectLoop方法来监听和处理启动应用的消息。
这个函数当有事件到来才会唤醒线程,然后调用ZygoteConnection的processOneCommand分析。最后这个函数返回的是子进程的函数入口的Runnable接口。
Runnable runSelectLoop(String abiList) {
......
while (true) {
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) {
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) {
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
try {
ZygoteConnection connection = peers.get(i);
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(i);
fds.remove(i);
}
}
} catch (Exception e) {
......
}
}
}
}
}
}
processOneCommand最后调用了Zygote.forkAndSpecialize来fork了应用进程。这里我们先主要看handleChildProc函数,这里主要是调用了ZygoteInit.zygoteInit函数。
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
parsedArgs.appDataDir);//fork子进程
try {
if (pid == 0) {
// in child
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
return handleChildProc(parsedArgs, descriptors, childPipeFd);//子进程初始化
} 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;
而这个函数中调用了nativeZygoteInit主要是初始化binder,而在applicationInit中就是返回了应用进程的函数入口(也就是ActivityThread的main函数)。
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);
}
我们再回到ZygoteInit的main函数,前面runSelectLoop返回的话肯定是子进程,而caller就是子进程的函数入口,后面调用caller的run函数就进入应用进程的ActivtityThread的main函数了。而Zygote的主进程依然在runSelectLoop中循环。
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();
}
预加载系统类和资源
为了加快应用程序的启动,Android把系统常用的java类和一部分Framework资源在zygote进程中预加载。这些预加载的类和资源在所有经zygote进程fork出的子进程中都是共享的。
前面我们在ZygoteInit的main中调用preload方法来加载系统资源,比如系统类,系统资源、opengl资源、共享库、webview资源等。
static void preload(TimingsTraceLog bootTimingsTraceLog) {
preloadClasses();
preloadResources();
nativePreloadAppProcessHALs();
preloadOpenGL();
preloadSharedLibraries();
preloadTextResources();
WebViewFactory.prepareWebViewInZygote();
}