赞
踩
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的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一个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类负责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();
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。