Android系统启动-zygote启动分析

发布时间:2024年01月23日

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

概述

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

/system/core/rootdir/init.rc

import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /init.usb.configfs.rc
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 service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
2     class main
3     priority -20
4     user root
5     group root readproc reserved_disk
6     socket zygote stream 660 root system
7     socket usap_pool_primary stream 660 root system
8     onrestart write /sys/android_power/request_state wake
9     onrestart write /sys/power/state on
10     onrestart restart audioserver
11     onrestart restart cameraserver
12     onrestart restart media
13     onrestart restart netd
14     onrestart restart wificond
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 LOCAL_PATH:= $(call my-dir)
2 
3 app_process_common_shared_libs := \
4     libandroid_runtime \
5     libbinder \
6     libcutils \
7     libdl \
8     libhidlbase \
9     liblog \
10     libnativeloader \
11     libutils \
12 
13 # This is a list of libraries that need to be included in order to avoid
14 # bad apps. This prevents a library from having a mismatch when resolving
15 # new/delete from an app shared library.
16 # See b/21032018 for more details.
17 app_process_common_shared_libs += \
18     libwilhelm \
19 
20 app_process_common_static_libs := \
21     libsigchain \
22 
23 app_process_src_files := \
24     app_main.cpp \


......


45 LOCAL_MODULE:= app_process
46 LOCAL_MULTILIB := both
47 LOCAL_MODULE_STEM_32 := app_process32
48 LOCAL_MODULE_STEM_64 := app_process64

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

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

int main(int argc,char* const argv) {  
 .....  

257      bool zygote = false;
258      bool startSystemServer = false;
259      bool application = false;
260      String8 niceName;
261      String8 className;
262  
263      ++i;  // Skip unused "parent dir" argument.
264      while (i < argc) {
265          const char* arg = argv[i++];
266          if (strcmp(arg, "--zygote") == 0) {
267              zygote = true;
268              niceName = ZYGOTE_NICE_NAME;
269          } else if (strcmp(arg, "--start-system-server") == 0) {
270              startSystemServer = true;
271          } else if (strcmp(arg, "--application") == 0) {
272              application = true;
273          } else if (strncmp(arg, "--nice-name=", 12) == 0) {
274              niceName.setTo(arg + 12);
275          } else if (strncmp(arg, "--", 2) != 0) {
276              className.setTo(arg);
277              break;
278          } else {
279              --i;
280              break;
281          }
282      }

.....  

335      if (zygote) {
336          runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
337      } else if (className) {
338          runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
339      } else {
340          fprintf(stderr, "Error: no class name or --zygote supplied.\n");
341          app_usage();
342          LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
343      }
}

这个函数解析了启动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

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)

    ...... 

      if (startVm(&mJavaVM, &env, zygote) != 0) {
          return;
      }
      onVmCreated(env);

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

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

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

 try {
          ......

              boolean startSystemServer = false;
              String zygoteSocketName = "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)) {
                      zygoteSocketName = 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.");
              }
  

              // In such cases, we will preload things prior to our first fork.
              if (!enableLazyPreload) {
                  // 预加载各类资源 
                  preload(bootTimingsTraceLog);
                  
              } 

  
  
              Zygote.initNativeState(isPrimaryZygote);
  
              ZygoteHooks.stopZygoteNoThreadCreation();
  
//  注册一个Socket 
              zygoteServer = new ZygoteServer(isPrimaryZygote);
  
              if (startSystemServer) {
                  Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
  
                  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);
          } catch (Throwable ex) {
              Log.e(TAG, "System zygote died with exception", ex);
              throw ex;
          } finally {
              if (zygoteServer != null) {
                  zygoteServer.closeServerSocket();
              }
          }

我们可以看到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

  private static Runnable forkSystemServer(String abiList, String socketName,
725              ZygoteServer zygoteServer) {
  String args[] = {
754                  "--setuid=1000",
755                  "--setgid=1000",
756                  "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
757                          + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
758                  "--capabilities=" + capabilities + "," + capabilities,
759                  "--nice-name=system_server",
760                  "--runtime-args",
761                  "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
762                  "com.android.server.SystemServer",
763          };
764          ZygoteArguments parsedArgs = null;
765  
766          int pid;
767  
768          try {
769              parsedArgs = new ZygoteArguments(args);
770              Zygote.applyDebuggerSystemProperty(parsedArgs);
771              Zygote.applyInvokeWithSystemProperty(parsedArgs);
772  
773              boolean profileSystemServer = SystemProperties.getBoolean(
774                      "dalvik.vm.profilesystemserver", false);
775              if (profileSystemServer) {
776                  parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
777              }
778  
779              /* Request to fork the system server process */
780              pid = Zygote.forkSystemServer(
781                      parsedArgs.mUid, parsedArgs.mGid,
782                      parsedArgs.mGids,
783                      parsedArgs.mRuntimeFlags,
784                      null,
785                      parsedArgs.mPermittedCapabilities,
786                      parsedArgs.mEffectiveCapabilities);
787          } catch (IllegalArgumentException ex) {
788              throw new RuntimeException(ex);
789          }
790  
791          /* For child process */
792          if (pid == 0) {
793              if (hasSecondZygote(abiList)) {
794                  waitForSecondaryZygote(socketName);
795              }
796  
797              zygoteServer.closeServerSocket();
798              return handleSystemServerProcess(parsedArgs);
799          }
800  
801          return null;
}

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

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

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

我们从runSelectLoop函数的?

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

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

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

  fd = null;
266  
267          pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
268                  parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
269                  parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
270                  parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion);
271  
272          try {
273              if (pid == 0) {
274                  // in child
275                  zygoteServer.setForkChild();
276  
277                  zygoteServer.closeServerSocket();
278                  IoUtils.closeQuietly(serverPipeFd);
279                  serverPipeFd = null;
280  
281                  return handleChildProc(parsedArgs, descriptors, childPipeFd,
282                          parsedArgs.mStartChildZygote);
283              } else {
284                  // In the parent. A pid < 0 indicates a failure and will be handled in
285                  // handleParentProc.
286                  IoUtils.closeQuietly(childPipeFd);
287                  childPipeFd = null;
288                  handleParentProc(pid, descriptors, serverPipeFd);
289                  return null;
290              }

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

我们跟一下forkAndSpecialize函数:?

 public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
235              int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
236              int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
237              int targetSdkVersion) {
238          ZygoteHooks.preFork();
239          // Resets nice priority for zygote process.
240          resetNicePriority();
241          int pid = nativeForkAndSpecialize(
242                  uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
243                  fdsToIgnore, startChildZygote, instructionSet, appDataDir);
244          // Enable tracing as soon as possible for the child process.
245          if (pid == 0) {
246              Zygote.disableExecuteOnly(targetSdkVersion);
247              Trace.setTracingEnabled(true, runtimeFlags);
248  
249              // Note that this event ends at the end of handleChildProc,
250              Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
251          }
252          ZygoteHooks.postForkCommon();
253          return pid;
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

文章来源:https://blog.csdn.net/Liang123l/article/details/132066082
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。