当前位置:   article > 正文

Zygote进程

zygote进程

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也会重启。

  1. service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
  2. class main
  3. priority -20
  4. user root
  5. group root readproc
  6. socket zygote stream 660 root system
  7. onrestart write /sys/android_power/request_state wake
  8. onrestart write /sys/power/state on
  9. onrestart restart audioserver
  10. onrestart restart cameraserver
  11. onrestart restart media
  12. onrestart restart netd
  13. onrestart restart wificond
  14. 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。

  1. bool zygote = false;
  2. bool startSystemServer = false;
  3. bool application = false;
  4. String8 niceName;
  5. String8 className;
  6. ++i; // Skip unused "parent dir" argument.
  7. while (i < argc) {
  8. const char* arg = argv[i++];
  9. if (strcmp(arg, "--zygote") == 0) {
  10. zygote = true;
  11. niceName = ZYGOTE_NICE_NAME;
  12. } else if (strcmp(arg, "--start-system-server") == 0) {
  13. startSystemServer = true;
  14. } else if (strcmp(arg, "--application") == 0) {
  15. application = true;
  16. } else if (strncmp(arg, "--nice-name=", 12) == 0) {
  17. niceName.setTo(arg + 12);
  18. } else if (strncmp(arg, "--", 2) != 0) {
  19. className.setTo(arg);
  20. break;
  21. } else {
  22. --i;
  23. break;
  24. }
  25. }

如果启动参数有--zygote执行ZygoteInit类,否则执行通过参数传进来的Java类。

  1. if (zygote) {
  2. runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
  3. } else if (className) {
  4. runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
  5. }

app_process除了能启动Zygote进程,也可以使用它来执行系统的某个java类,比如am命令。

AndroidRuntime

AndroidRuntime一个Android底层的一个类,负责启动虚拟机java线程。AndroidRuntime类在一个进程中只有一个实例对象。

前面在app_process的main函数中最后调用了AndroidRuntime的start函数。这个函数主要启动虚拟机,然后通过CallStaticVoidMethod函数来调用java层的函数。这样Zygote的初始化过程转到了java层了。当然如果启动的不是Zygote而是执行的java类将是调用RuntimeInit函数。

  1. void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
  2. {
  3. ALOGD(">>>>>> START %s uid %d <<<<<<\n",
  4. className != NULL ? className : "(unknown)", getuid());
  5. static const String8 startSystemServer("start-system-server");
  6. /*
  7. * 'startSystemServer == true' means runtime is obsolete and not run from
  8. * init.rc anymore, so we print out the boot start event here.
  9. */
  10. for (size_t i = 0; i < options.size(); ++i) {
  11. if (options[i] == startSystemServer) {
  12. /* track our progress through the boot sequence */
  13. const int LOG_BOOT_PROGRESS_START = 3000;
  14. LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
  15. }
  16. }
  17. const char* rootDir = getenv("ANDROID_ROOT");
  18. if (rootDir == NULL) {
  19. rootDir = "/system";
  20. if (!hasDir("/system")) {
  21. LOG_FATAL("No root directory specified, and /android does not exist.");
  22. return;
  23. }
  24. setenv("ANDROID_ROOT", rootDir, 1);
  25. }
  26. //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
  27. //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
  28. /* start the virtual machine */
  29. JniInvocation jni_invocation;
  30. jni_invocation.Init(NULL);
  31. JNIEnv* env;
  32. if (startVm(&mJavaVM, &env, zygote) != 0) {
  33. return;
  34. }
  35. onVmCreated(env);
  36. /*
  37. * Register android functions.
  38. */
  39. if (startReg(env) < 0) {
  40. ALOGE("Unable to register all android natives\n");
  41. return;
  42. }
  43. ......
  44. /*
  45. * Start VM. This thread becomes the main thread of the VM, and will
  46. * not return until the VM exits.
  47. */
  48. char* slashClassName = toSlashClassName(className != NULL ? className : "");
  49. jclass startClass = env->FindClass(slashClassName);
  50. if (startClass == NULL) {
  51. ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
  52. /* keep going */
  53. } else {
  54. jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
  55. "([Ljava/lang/String;)V");
  56. if (startMeth == NULL) {
  57. ALOGE("JavaVM unable to find main() in '%s'\n", className);
  58. /* keep going */
  59. } else {
  60. env->CallStaticVoidMethod(startClass, startMeth, strArray);
  61. }
  62. }

ZygoteInit

ZygoteInit类负责Zygote进程java层的初始化工作。这个类的main函数主要注册了zygote的socket来监听应用程序的启动消息,加载资源、启动systemserver、然后进入socket监听等。我们需要注意这个函数已经fork了一个system_server并且zygote主线程最后在执行runSelectLoop函数监听其他应用进程启动的消息。当有启动进程的socket消息,runSelectLoop函数就会返回,当然这个时候返回是在子进程中,zygote进程还是不听监控socket,最后通过返回的caller,然后执行器run函数。这样就到应用进程的ActivityThread的main函数了。

  1. public static void main(String argv[]) {
  2. ZygoteServer zygoteServer = new ZygoteServer();
  3. ......
  4. final Runnable caller;
  5. try {
  6. ......
  7. boolean startSystemServer = false;
  8. String socketName = "zygote";
  9. String abiList = null;
  10. boolean enableLazyPreload = false;
  11. for (int i = 1; i < argv.length; i++) {
  12. if ("start-system-server".equals(argv[i])) {
  13. startSystemServer = true;
  14. } else if ("--enable-lazy-preload".equals(argv[i])) {
  15. enableLazyPreload = true;
  16. } else if (argv[i].startsWith(ABI_LIST_ARG)) {
  17. abiList = argv[i].substring(ABI_LIST_ARG.length());
  18. } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
  19. socketName = argv[i].substring(SOCKET_NAME_ARG.length());
  20. } else {
  21. throw new RuntimeException("Unknown command line argument: " + argv[i]);
  22. }
  23. }
  24. if (abiList == null) {
  25. throw new RuntimeException("No ABI list supplied.");
  26. }
  27. zygoteServer.registerServerSocket(socketName);//注册socket监听,用来接收启动应用启动的消息
  28. // In some configurations, we avoid preloading resources and classes eagerly.
  29. // In such cases, we will preload things prior to our first fork.
  30. if (!enableLazyPreload) {
  31. preload(bootTimingsTraceLog);//加载资源
  32. } else {
  33. Zygote.resetNicePriority();
  34. }
  35. // Do an initial gc to clean up after startup
  36. bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
  37. gcAndFinalize();
  38. bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC
  39. bootTimingsTraceLog.traceEnd(); // ZygoteInit
  40. // Disable tracing so that forked processes do not inherit stale tracing tags from
  41. // Zygote.
  42. Trace.setTracingEnabled(false, 0);
  43. // Zygote process unmounts root storage spaces.
  44. Zygote.nativeUnmountStorageOnInit();
  45. // Set seccomp policy
  46. Seccomp.setPolicy();
  47. ZygoteHooks.stopZygoteNoThreadCreation();
  48. if (startSystemServer) {
  49. Runnable r = forkSystemServer(abiList, socketName, zygoteServer);//启动systemserver进程
  50. // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
  51. // child (system_server) process.
  52. if (r != null) {
  53. r.run();
  54. return;
  55. }
  56. }
  57. Log.i(TAG, "Accepting command socket connections");
  58. // The select loop returns early in the child process after a fork and
  59. // loops forever in the zygote.
  60. caller = zygoteServer.runSelectLoop(abiList);//监听socket消息,并且获取到java的函数入口,这里zygote会一直循环,能返回的都是fork出来的子进程
  61. } catch (Throwable ex) {
  62. Log.e(TAG, "System zygote died with exception", ex);
  63. throw ex;
  64. } finally {
  65. zygoteServer.closeServerSocket();
  66. }
  67. // We're in the child process and have exited the select loop. Proceed to execute the
  68. // command.
  69. if (caller != null) {
  70. caller.run();//这个时候在子进程中,一般调用ActivityThread的main方法了
  71. }
  72. }

请求启动应用进程

Android启动一个新的进程都是在AMS中通过其startProcessLocked函数来完成,这个我们在之前分析AMS的博客分析过了。

这个函数最后会调用如下代码,而这个entryPoint就是android.app.ActivityThread

  1. startResult = Process.start(entryPoint,
  2. app.processName, uid, uid, gids, debugFlags, mountExternal,
  3. app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
  4. app.info.dataDir, invokeWith, entryPointArgs);

而最后是调用了ZygotePrcocess的startViaZygote函数,这个函数又调用了zygoteSendArgsAndGetResult函数,而zygoteSendArgsAndGetResult这个函数把会这些参数通过socket传给zygote,而我们现在的进程就是system_server。

然后我们再来看zygote进程的ZygoteInit类中main方法调用的runSelectLoop方法来监听和处理启动应用的消息。

这个函数当有事件到来才会唤醒线程,然后调用ZygoteConnection的processOneCommand分析。最后这个函数返回的是子进程的函数入口的Runnable接口。

  1. Runnable runSelectLoop(String abiList) {
  2. ......
  3. while (true) {
  4. StructPollfd[] pollFds = new StructPollfd[fds.size()];
  5. for (int i = 0; i < pollFds.length; ++i) {
  6. pollFds[i] = new StructPollfd();
  7. pollFds[i].fd = fds.get(i);
  8. pollFds[i].events = (short) POLLIN;
  9. }
  10. try {
  11. Os.poll(pollFds, -1);
  12. } catch (ErrnoException ex) {
  13. throw new RuntimeException("poll failed", ex);
  14. }
  15. for (int i = pollFds.length - 1; i >= 0; --i) {
  16. if ((pollFds[i].revents & POLLIN) == 0) {
  17. continue;
  18. }
  19. if (i == 0) {
  20. ZygoteConnection newPeer = acceptCommandPeer(abiList);
  21. peers.add(newPeer);
  22. fds.add(newPeer.getFileDesciptor());
  23. } else {
  24. try {
  25. ZygoteConnection connection = peers.get(i);
  26. final Runnable command = connection.processOneCommand(this);
  27. if (mIsForkChild) {
  28. // We're in the child. We should always have a command to run at this
  29. // stage if processOneCommand hasn't called "exec".
  30. if (command == null) {
  31. throw new IllegalStateException("command == null");
  32. }
  33. return command;//子进程就返回函数入口
  34. } else {
  35. // We're in the server - we should never have any commands to run.
  36. if (command != null) {
  37. throw new IllegalStateException("command != null");
  38. }
  39. // We don't know whether the remote side of the socket was closed or
  40. // not until we attempt to read from it from processOneCommand. This shows up as
  41. // a regular POLLIN event in our regular processing loop.
  42. if (connection.isClosedByPeer()) {
  43. connection.closeSocket();
  44. peers.remove(i);
  45. fds.remove(i);
  46. }
  47. }
  48. } catch (Exception e) {
  49. ......
  50. }
  51. }
  52. }
  53. }
  54. }
  55. }

processOneCommand最后调用了Zygote.forkAndSpecialize来fork了应用进程。这里我们先主要看handleChildProc函数,这里主要是调用了ZygoteInit.zygoteInit函数。

  1. pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
  2. parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
  3. parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
  4. parsedArgs.appDataDir);//fork子进程
  5. try {
  6. if (pid == 0) {
  7. // in child
  8. zygoteServer.setForkChild();
  9. zygoteServer.closeServerSocket();
  10. IoUtils.closeQuietly(serverPipeFd);
  11. serverPipeFd = null;
  12. return handleChildProc(parsedArgs, descriptors, childPipeFd);//子进程初始化
  13. } else {
  14. // In the parent. A pid < 0 indicates a failure and will be handled in
  15. // handleParentProc.
  16. IoUtils.closeQuietly(childPipeFd);
  17. childPipeFd = null;
  18. handleParentProc(pid, descriptors, serverPipeFd);
  19. return null;

而这个函数中调用了nativeZygoteInit主要是初始化binder,而在applicationInit中就是返回了应用进程的函数入口(也就是ActivityThread的main函数)。

  1. public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
  2. if (RuntimeInit.DEBUG) {
  3. Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
  4. }
  5. Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
  6. RuntimeInit.redirectLogStreams();
  7. RuntimeInit.commonInit();
  8. ZygoteInit.nativeZygoteInit();
  9. return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
  10. }

我们再回到ZygoteInit的main函数,前面runSelectLoop返回的话肯定是子进程,而caller就是子进程的函数入口,后面调用caller的run函数就进入应用进程的ActivtityThread的main函数了。而Zygote的主进程依然在runSelectLoop中循环。

  1. caller = zygoteServer.runSelectLoop(abiList);
  2. } catch (Throwable ex) {
  3. Log.e(TAG, "System zygote died with exception", ex);
  4. throw ex;
  5. } finally {
  6. zygoteServer.closeServerSocket();
  7. }
  8. // We're in the child process and have exited the select loop. Proceed to execute the
  9. // command.
  10. if (caller != null) {
  11. caller.run();
  12. }

预加载系统类和资源

为了加快应用程序的启动,Android把系统常用的java类和一部分Framework资源在zygote进程中预加载。这些预加载的类和资源在所有经zygote进程fork出的子进程中都是共享的。

前面我们在ZygoteInit的main中调用preload方法来加载系统资源,比如系统类,系统资源、opengl资源、共享库、webview资源等。

  1. static void preload(TimingsTraceLog bootTimingsTraceLog) {
  2. preloadClasses();
  3. preloadResources();
  4. nativePreloadAppProcessHALs();
  5. preloadOpenGL();
  6. preloadSharedLibraries();
  7. preloadTextResources();
  8. WebViewFactory.prepareWebViewInZygote();
  9. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/227940
推荐阅读
相关标签
  

闽ICP备14008679号