当前位置:   article > 正文

Android系统启动-zygote启动分析_andorid zygote启动分析

andorid zygote启动分析

基于Android10.0的源码分析Android启动的Zygote进程

概述

Zygote这个词的字面意思是“受精卵”,因而可以孕育出一个新生命。正如其所示Android中大多数应用进程和系统进程都是Zygote来生成的。 那么Zygote是如何启动的,也是由init解析rc脚本时启动。早期Android版本zygote命令直接写在init.rc中,但是随着硬件不断升级换代,Android系统不的不面对32位和64位机器同时存在情况,因为对zygote启动也需要根据不同情况区分对待: 

  1. /system/core/rootdir/init.rc
  2. import /init.environ.rc
  3. import /init.usb.rc
  4. import /init.${ro.hardware}.rc
  5. import /vendor/etc/init/hw/init.${ro.hardware}.rc
  6. import /init.usb.configfs.rc
  7. import /init.${ro.zygote}.rc

根据ro.zygote的具体值,我们需要加载不同的zygote的rc脚本,例如:  

init.zygote32.rc

init.zygote32_64.rc

init.zygote64.rc

init.zygote64_32.rc

zygote启动过程

我们以init.zygote64.rc为例子,相关代码如下: 

  1. 1 service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
  2. 2 class main
  3. 3 priority -20
  4. 4 user root
  5. 5 group root readproc reserved_disk
  6. 6 socket zygote stream 660 root system
  7. 7 socket usap_pool_primary stream 660 root system
  8. 8 onrestart write /sys/android_power/request_state wake
  9. 9 onrestart write /sys/power/state on
  10. 10 onrestart restart audioserver
  11. 11 onrestart restart cameraserver
  12. 12 onrestart restart media
  13. 13 onrestart restart netd
  14. 14 onrestart restart wificond
  15. 15 writepid /dev/cpuset/foreground/tasks

从该段脚本看出: 

服务名(Servicename): zygote 

路径(Path): /system/bin/app_process64

参数(Arguments): -Xzygote  /system/bin  --start-system-server 

Zygote所属的class为main,而不是core。从路径可以看出,它所在程序名叫“app_process64”。通过--zygote参数,app_process可以识别出用户是否需要启动zygote,我们来看下app_process是什么?源码路径frameworks/base/cmds/ ,先看它的Android.mk 

  1. 1 LOCAL_PATH:= $(call my-dir)
  2. 2
  3. 3 app_process_common_shared_libs := \
  4. 4 libandroid_runtime \
  5. 5 libbinder \
  6. 6 libcutils \
  7. 7 libdl \
  8. 8 libhidlbase \
  9. 9 liblog \
  10. 10 libnativeloader \
  11. 11 libutils \
  12. 12
  13. 13 # This is a list of libraries that need to be included in order to avoid
  14. 14 # bad apps. This prevents a library from having a mismatch when resolving
  15. 15 # new/delete from an app shared library.
  16. 16 # See b/21032018 for more details.
  17. 17 app_process_common_shared_libs += \
  18. 18 libwilhelm \
  19. 19
  20. 20 app_process_common_static_libs := \
  21. 21 libsigchain \
  22. 22
  23. 23 app_process_src_files := \
  24. 24 app_main.cpp \
  25. ......
  26. 45 LOCAL_MODULE:= app_process
  27. 46 LOCAL_MULTILIB := both
  28. 47 LOCAL_MODULE_STEM_32 := app_process32
  29. 48 LOCAL_MODULE_STEM_64 := app_process64

上述就是Multilib(64位和32位系统)的一个编译脚本范例。其中LOCAL_MULTLIB用于希望针对的硬件架构平台。

分析一下函数app_process的主函数实现:

  1. int main(int argc,char* const argv) {
  2. .....
  3. 257 bool zygote = false;
  4. 258 bool startSystemServer = false;
  5. 259 bool application = false;
  6. 260 String8 niceName;
  7. 261 String8 className;
  8. 262
  9. 263 ++i; // Skip unused "parent dir" argument.
  10. 264 while (i < argc) {
  11. 265 const char* arg = argv[i++];
  12. 266 if (strcmp(arg, "--zygote") == 0) {
  13. 267 zygote = true;
  14. 268 niceName = ZYGOTE_NICE_NAME;
  15. 269 } else if (strcmp(arg, "--start-system-server") == 0) {
  16. 270 startSystemServer = true;
  17. 271 } else if (strcmp(arg, "--application") == 0) {
  18. 272 application = true;
  19. 273 } else if (strncmp(arg, "--nice-name=", 12) == 0) {
  20. 274 niceName.setTo(arg + 12);
  21. 275 } else if (strncmp(arg, "--", 2) != 0) {
  22. 276 className.setTo(arg);
  23. 277 break;
  24. 278 } else {
  25. 279 --i;
  26. 280 break;
  27. 281 }
  28. 282 }
  29. .....
  30. 335 if (zygote) {
  31. 336 runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
  32. 337 } else if (className) {
  33. 338 runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
  34. 339 } else {
  35. 340 fprintf(stderr, "Error: no class name or --zygote supplied.\n");
  36. 341 app_usage();
  37. 342 LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
  38. 343 }
  39. }

这个函数解析了启动app_process时传入参数:

--zygote : 表示当前进程用于承载zygote 。

--start-system-server : 是否需要驱动system_server 。

--application:启动进入独立的程序模式。 

--nice-name:此进程的 “别名” 。

整一个场景中,init.rc 指定了--zygote选项,所以app_process接下来启动ZygoteInit,并且传入了“start-system-server”。之后ZygoteInit会运行Java虚拟机上,这是因为runtime就是AndroidRuntime,我们看下AndroidRuntime核心start代码 

frameworks/base/core/jni/AndroidRuntime.cpp

  1. void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
  2. ......
  3. if (startVm(&mJavaVM, &env, zygote) != 0) {
  4. return;
  5. }
  6. onVmCreated(env);

对于虚拟机具体启动和运行过程,本章略过 。

那么虚拟及启动成功后,并进入ZygoteInit的执行中:

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

  1. try {
  2. ......
  3. boolean startSystemServer = false;
  4. String zygoteSocketName = "zygote";
  5. String abiList = null;
  6. boolean enableLazyPreload = false;
  7. for (int i = 1; i < argv.length; i++) {
  8. if ("start-system-server".equals(argv[i])) {
  9. startSystemServer = true;
  10. } else if ("--enable-lazy-preload".equals(argv[i])) {
  11. enableLazyPreload = true;
  12. } else if (argv[i].startsWith(ABI_LIST_ARG)) {
  13. abiList = argv[i].substring(ABI_LIST_ARG.length());
  14. } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
  15. zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
  16. } else {
  17. throw new RuntimeException("Unknown command line argument: " + argv[i]);
  18. }
  19. }
  20. if (abiList == null) {
  21. throw new RuntimeException("No ABI list supplied.");
  22. }
  23. // In such cases, we will preload things prior to our first fork.
  24. if (!enableLazyPreload) {
  25. // 预加载各类资源
  26. preload(bootTimingsTraceLog);
  27. }
  28. Zygote.initNativeState(isPrimaryZygote);
  29. ZygoteHooks.stopZygoteNoThreadCreation();
  30. // 注册一个Socket
  31. zygoteServer = new ZygoteServer(isPrimaryZygote);
  32. if (startSystemServer) {
  33. Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
  34. if (r != null) {
  35. r.run();
  36. return;
  37. }
  38. }
  39. Log.i(TAG, "Accepting command socket connections");
  40. // The select loop returns early in the child process after a fork and
  41. // loops forever in the zygote.
  42. caller = zygoteServer.runSelectLoop(abiList);
  43. } catch (Throwable ex) {
  44. Log.e(TAG, "System zygote died with exception", ex);
  45. throw ex;
  46. } finally {
  47. if (zygoteServer != null) {
  48. zygoteServer.closeServerSocket();
  49. }
  50. }

我们可以看到ZygoteInit主函数主要完成以下几项工作:

1. 注册一个socket 

2. 预加载各类资源

包括:
          preloadClasses();
          cacheNonBootClasspathClassLoaders();
          preloadResources();
          nativePreloadAppProcessHALs();
          maybePreloadGraphicsDriver();
          preloadSharedLibraries();
          preloadTextResources();
          WebViewFactory.prepareWebViewInZygote();

已preloadClasses为例子,他负责加载和初始化常用的一些calsses,这个记录都是在framework/base/tools/preload/WritePreloadClassFile.java生成的 。

启动System Server 

因为app_aprocess的调用带有“--start-system-server”,那么此时就会通过forkSystemServer函数来启动System Server。

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

  1. private static Runnable forkSystemServer(String abiList, String socketName,
  2. 725 ZygoteServer zygoteServer) {
  3. String args[] = {
  4. 754 "--setuid=1000",
  5. 755 "--setgid=1000",
  6. 756 "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
  7. 757 + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
  8. 758 "--capabilities=" + capabilities + "," + capabilities,
  9. 759 "--nice-name=system_server",
  10. 760 "--runtime-args",
  11. 761 "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
  12. 762 "com.android.server.SystemServer",
  13. 763 };
  14. 764 ZygoteArguments parsedArgs = null;
  15. 765
  16. 766 int pid;
  17. 767
  18. 768 try {
  19. 769 parsedArgs = new ZygoteArguments(args);
  20. 770 Zygote.applyDebuggerSystemProperty(parsedArgs);
  21. 771 Zygote.applyInvokeWithSystemProperty(parsedArgs);
  22. 772
  23. 773 boolean profileSystemServer = SystemProperties.getBoolean(
  24. 774 "dalvik.vm.profilesystemserver", false);
  25. 775 if (profileSystemServer) {
  26. 776 parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
  27. 777 }
  28. 778
  29. 779 /* Request to fork the system server process */
  30. 780 pid = Zygote.forkSystemServer(
  31. 781 parsedArgs.mUid, parsedArgs.mGid,
  32. 782 parsedArgs.mGids,
  33. 783 parsedArgs.mRuntimeFlags,
  34. 784 null,
  35. 785 parsedArgs.mPermittedCapabilities,
  36. 786 parsedArgs.mEffectiveCapabilities);
  37. 787 } catch (IllegalArgumentException ex) {
  38. 788 throw new RuntimeException(ex);
  39. 789 }
  40. 790
  41. 791 /* For child process */
  42. 792 if (pid == 0) {
  43. 793 if (hasSecondZygote(abiList)) {
  44. 794 waitForSecondaryZygote(socketName);
  45. 795 }
  46. 796
  47. 797 zygoteServer.closeServerSocket();
  48. 798 return handleSystemServerProcess(parsedArgs);
  49. 799 }
  50. 800
  51. 801 return null;
  52. }

上述的代码又出现了fork流程--forkSytemServer在利用内部UNIX的fork机制来创建一个新进程。 

随后在执行过程中通过handleSystemServerProcess来启动各种支撑系统运行的System Server 。 

我们来分析一下Zygote的工作做一个分析,forkSystemServer中并没有为父进程专门开辟一个代码分支,返回很正常Runnable后,返回到了ZygoteInit函数的 runSelectLoop ,我们可以看到这是一个死循环 ,除非Zygote退出或者异常才会跳出循环。 

我们从runSelectLoop函数的 

  1. Runnable runSelectLoop(String abiList) {
  2. ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>();
  3. ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
  4. socketFDs.add(mZygoteSocket.getFileDescriptor());
  5. peers.add(null);
获取到前面的ZygoteServer创建的Server Socket文件描述符,他会被添加到ArrayList<FileDescriptor>类型的fds中。

当有客户端的数据需要处理时候,完成具体工作是processOneCommand 函数 

/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

  1. fd = null;
  2. 266
  3. 267 pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
  4. 268 parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
  5. 269 parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
  6. 270 parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion);
  7. 271
  8. 272 try {
  9. 273 if (pid == 0) {
  10. 274 // in child
  11. 275 zygoteServer.setForkChild();
  12. 276
  13. 277 zygoteServer.closeServerSocket();
  14. 278 IoUtils.closeQuietly(serverPipeFd);
  15. 279 serverPipeFd = null;
  16. 280
  17. 281 return handleChildProc(parsedArgs, descriptors, childPipeFd,
  18. 282 parsedArgs.mStartChildZygote);
  19. 283 } else {
  20. 284 // In the parent. A pid < 0 indicates a failure and will be handled in
  21. 285 // handleParentProc.
  22. 286 IoUtils.closeQuietly(childPipeFd);
  23. 287 childPipeFd = null;
  24. 288 handleParentProc(pid, descriptors, serverPipeFd);
  25. 289 return null;
  26. 290 }

zygote需要为每个新启动的应用程序生成独立的进程。. 不过没有直接用fork来完成,而是调用了forkAndSpecialize函数,新进程运行应用程序本身代码,这些工作在函数 handleChildProc函数中进行。 

我们跟一下forkAndSpecialize函数: 

  1. public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
  2. 235 int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
  3. 236 int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
  4. 237 int targetSdkVersion) {
  5. 238 ZygoteHooks.preFork();
  6. 239 // Resets nice priority for zygote process.
  7. 240 resetNicePriority();
  8. 241 int pid = nativeForkAndSpecialize(
  9. 242 uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
  10. 243 fdsToIgnore, startChildZygote, instructionSet, appDataDir);
  11. 244 // Enable tracing as soon as possible for the child process.
  12. 245 if (pid == 0) {
  13. 246 Zygote.disableExecuteOnly(targetSdkVersion);
  14. 247 Trace.setTracingEnabled(true, runtimeFlags);
  15. 248
  16. 249 // Note that this event ends at the end of handleChildProc,
  17. 250 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
  18. 251 }
  19. 252 ZygoteHooks.postForkCommon();
  20. 253 return pid;
  21. 254 }

处理分为3个阶段:preFork  、 nativeForkAndSpecialize 、postForkCommon 

总结

从以上的分析可以得知,Zygote进程启动中承担的主要职责如下:

  • 1、创建AppRuntime,执行其start方法,启动Zygote进程。。
  • 2、创建JVM并为JVM注册JNI方法。
  • 3、使用JNI调用ZygoteInit的main函数进入Zygote的Java FrameWork层。
  • 4、使用ZygoteServer创建服务器端Socket,并通过runSelectLoop方法等等AMS的请求去创建新的应用进程。
  • 5、启动SystemServer进程。

Android源码参考链接

参考:

书籍: 深入理解Android内核设计思想 第2版(上册)

博客:  Android系统启动流程之Zygote进程启动 | Deep into Android

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号