Zygote启动流程解析

目录

1.什么是Zygote?

2. Zygote脚本启动

3.Zygote进程启动


1.什么是Zygote?

    Zygote是Android系统创建的第一个Java进程,它是所有Java进程的父进程。Zygote进程作为Socket的Server端,接收处理系统中创建进程的请求。Android中的应用进程的创建都是应用进程通过Binder发送请求给SystemServer,SystemServer再发送Socket消息给Zygote进程,统一由Zygote进程创建出来的。整个过程如下图所示:

         

    进程的创建采用Zygote创建的话有以下几点原因:

    1.Zygote进程在启动的时候会创建一个虚拟机实例,因此通过Zygote进程创建的子进程都会继承这个虚拟机实例,app中的Java代码都可以得到翻译执行。

    2.Zygote创建的子进程还可以获得一个Binder线程池,这样进程之间就可以通过Binder进行跨进程通信了。

2. Zygote脚本启动

    init进程是Android用户空间的第一个进程,也就是说其他所有的进程都是直接或者间接由init进程fork出来的。Zygote也不例外,它是在系统启动过程中由init进程创建的。所以讲解Zygote的创建需要由init进程的创建展开。

    Android 10.0 之后init的入口函数由init.cpp变为了main.cpp,并且将各个阶段的代码进行了 划分,使其结构更清晰。

//system/core/init/main.cpp
51  int main(int argc, char** argv) {
52  #if __has_feature(address_sanitizer)
53      __asan_set_error_report_callback(AsanReportCallback);
54  #endif
55  
56      if (!strcmp(basename(argv[0]), "ueventd")) {
57          return ueventd_main(argc, argv);
58      }
59  
60      if (argc > 1) {
61          if (!strcmp(argv[1], "subcontext")) {
62              android::base::InitLogging(argv, &android::base::KernelLogger);
63              const BuiltinFunctionMap function_map;
64  
65              return SubcontextMain(argc, argv, &function_map);
66          }
67  
68          if (!strcmp(argv[1], "selinux_setup")) {
69              return SetupSelinux(argv);
70          }
71  
72          if (!strcmp(argv[1], "second_stage")) {
73              return SecondStageMain(argc, argv);
74          }
75      }
76  
77      return FirstStageMain(argc, argv);
78  }

    通过对system/core/init/README.md的阅读可以知道main函数会被执行多次,启动的顺序是ueventd_main->FirstStageMain

->SetupSelinux->SecondStageMain。

    1)ueventd_main主要功能:

    1.解析ueventd相关rc文件,管理设备节点权限

    2.Cold boot,递归扫描/sys目录,根据uevent文件,静态创建设备节点

    3.Hot plug, 获取内核uevent 事件,动态创建设备节点。

    2)FirstStageMain主要功能:

    1.创建文件系统目录并挂载相关的文件系统

    2.屏蔽标准的输入输出/初始化内核log系统

    3)SetupSeLinux主要功能:

    1.初始化SElinux,加载SELinux规则,配置SELinux相关log输出,并启动第二阶段。

    4)SecondStageMain主要功能(重点关注部分):

    1.创建进程会话秘钥并初始化属性系统

    2.进行SELinux第二阶段并恢复一些文件安全上下文

    3.新建epoll并初始化子进程中止信号处理函数

    4.启动属性服务

    5.解析init.rc等文件,启动其他进程

    SecondStageMain的部分具体通过代码来看一下:

//system/core/init/init.cpp
618  int SecondStageMain(int argc, char** argv) {
619      if (REBOOT_BOOTLOADER_ON_PANIC) {
620          InstallRebootSignalHandlers();
621      }
     ........
         //系统初始化
643      property_init();
674      // Now set up SELinux for second stage.
675      SelinuxSetupKernelLogging();
676      SelabelInitialize();
677      SelinuxRestoreContext();
678  
         //注册信号处理
679      Epoll epoll;
680      if (auto result = epoll.Open(); !result) {
681          PLOG(FATAL) << result.error();
682      }
683  
684      InstallSignalFdHandler(&epoll);
      ........
         //启动系统属性服务
690      StartPropertyService(&epoll);
      ........
         //解析.rc文件
706      LoadBootScripts(am, sm);
      ........
         //加入触发early-init语句
721      am.QueueEventTrigger("early-init");
      ........
         //加入触发init语句
742      am.QueueEventTrigger("init");
      ........
         //加入触发late-init语句
756      if (bootmode == "charger") {
757          am.QueueEventTrigger("charger");
758      } else {
759          am.QueueEventTrigger("late-init");
760      }
      ........
             //执行所有触发器队列中Action command的执行函数
776          if (!(waiting_for_prop || Service::is_exec_service_running())) {
777              am.ExecuteOneCommand();
778          }

    LoadBootScripts(am, sm)会执行解析init.rc的操作,init.rc是一个配置文件,它内部是由Android初始化语言(Android Init Language)编写的脚本,它主要包含五种类型的语句:Action,Commands,Services,Options和Import。本篇博客主要探讨Zygote的启动流程,关于初始化语言的用法可以参考源码中的README,里面有详细的使用说明。

    Zygote的启动脚本是通过Import语句引入到init.rc中的。

//system/core/rootdir/init.rc
10 import /vendor/etc/init/hw/init.${ro.hardware}.rc
11 import /init.usb.configfs.rc
12 import /init.${ro.zygote}.rc

    这里根据属性ro.zygote的内容来引入不同的Zygote启动脚本。Android 5.0以后,Android开始支持64位编译,Zygote进程也随之引入了32/64位的区别。所以,这里通过ro.zygote属性来控制启动不同版本的Zygote进程。
ro.zygote属性会有四种不同的值:

zygote32:代表32位模式
zygote32_64:代表32模式为主,64位模式为辅
zygote64:代表64位模式
zygote64_32:代表64模式为主,32位模式为辅
    Zygote启动脚本的路径为system/core/rootdir。

    这里我们以64位处理器为例,init.zygote64.rc代码如下:

//system/core/rootdir/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

    为了分析Zygote的创建,我们需要看下Services类型的语句格式:

service <name> <pathname> [ <argument> ]* //service名字 执行路径 参数

<option> //option是service的修饰词,影响什么时候,如何启动service

<option> ...

    Android中有专门的函数对service进行解析,一个是ParseSection,它会解析service的rc文件,它的主要作用就是搭建service的框架,另一个函数ParseLineSection用来解析子项。

    有了services类型语句格式的介绍,我们就可以知道Zygote进行的名字为zygote,执行路径为/system/bin/app_process64。注册了service之后,就是在一个合适的时机对它进行调用。我们回到我们上面init.rc中

         //解析.rc文件
706      LoadBootScripts(am, sm);
      ........
         //加入触发early-init语句
721      am.QueueEventTrigger("early-init");
      ........
         //加入触发init语句
742      am.QueueEventTrigger("init");
      ........
         //加入触发late-init语句
756      if (bootmode == "charger") {
757          am.QueueEventTrigger("charger");
758      } else {
759          am.QueueEventTrigger("late-init");
760      }
      ........
             //执行所有触发器队列中Action command的执行函数
             //这个地方就会依次执行我们上面加入的触发语句,也就是依次执行early-init,init,late-init
776          if (!(waiting_for_prop || Service::is_exec_service_running())) {
777              am.ExecuteOneCommand();
778          }

    start Zygote的操作在late-init中,我们看下late-init

//system/core/rootdir/init.rc
314 # Mount filesystems and start core system services.
315 on late-init
316     trigger early-fs
    ........
339     # Now we can start zygote for devices with file based encryption
340     trigger zygote-start
    ........


//triger zygote
626 # It is recommended to put unnecessary data/ initialization from post-fs-data
627 # to start-zygote in device's init.rc to unblock zygote start.
628 on zygote-start && property:ro.crypto.state=unencrypted
629     # A/B update verifier that marks a successful boot.
630     exec_start update_verifier_nonencrypted
631     start netd
632     start zygote
633     start zygote_secondary
634 
635 on zygote-start && property:ro.crypto.state=unsupported
636     # A/B update verifier that marks a successful boot.
637     exec_start update_verifier_nonencrypted
638     start netd
639     start zygote
640     start zygote_secondary
641 
642 on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
643     # A/B update verifier that marks a successful boot.
644     exec_start update_verifier_nonencrypted
645     start netd
646     start zygote
647     start zygote_secondary

    start命令对应的执行函数为do_start,定义在platform/system/core/init/builtings.cpp,这个对应关系式在parseService的时候建立的。

//system/core/init/builtins.cpp
1193  // Builtin-function-map start
1194  const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
1195      constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
1196      // clang-format off
1197      static const Map builtin_functions = {
1198          {"bootchart",               {1,     1,    {false,  do_bootchart}}},
1199          {"chmod",                   {2,     2,    {true,   do_chmod}}},
1200          {"chown",                   {2,     3,    {true,   do_chown}}},
1201          {"class_reset",             {1,     1,    {false,  do_class_reset}}},
1202          {"class_reset_post_data",   {1,     1,    {false,  do_class_reset_post_data}}},
1203          {"class_restart",           {1,     1,    {false,  do_class_restart}}},
1204          {"class_start",             {1,     1,    {false,  do_class_start}}},
1205          {"class_start_post_data",   {1,     1,    {false,  do_class_start_post_data}}},
1206          {"class_stop",              {1,     1,    {false,  do_class_stop}}},
1207          {"copy",                    {2,     2,    {true,   do_copy}}},
1208          {"domainname",              {1,     1,    {true,   do_domainname}}},
1209          {"enable",                  {1,     1,    {false,  do_enable}}},
        ........
1244          {"start",                   {1,     1,    {false,  do_start}}},
        ........

715  static Result<Success> do_start(const BuiltinArguments& args) {
716      Service* svc = ServiceList::GetInstance().FindService(args[1]);
717      if (!svc) return Error() << "service " << args[1] << " not found";
718      if (auto result = svc->Start(); !result) {
719          return Error() << "Could not start service: " << result.error();
720      }
721      return Success();
722  }
//system/core/init/service.cpp
887  Result<Success> Service::Start() {
888      if (is_updatable() && !ServiceList::GetInstance().IsServicesUpdated()) {
889          ServiceList::GetInstance().DelayService(*this);
890          return Error() << "Cannot start an updatable service '" << name_
891                         << "' before configs from APEXes are all loaded. "
892                         << "Queued for execution.";
893      }
     ........
         //从init进程中fork出zygote进程
958      pid_t pid = -1;
959      if (namespace_flags_) {
960          pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);
961      } else {
962          pid = fork();
963      }
964  
     ........
              //为zygote创建socket,详情见下
1001          std::for_each(descriptors_.begin(), descriptors_.end(),
1002                        std::bind(&DescriptorInfo::CreateAndPublish, std::placeholders::_1, scon));
     ........
              //启动zygote,详情见下
1057          if (!ExpandArgsAndExecv(args_, sigstop_)) {
1058              PLOG(ERROR) << "cannot execve('" << args_[0] << "')";
1059          }
1060  
1061          _exit(127);
1062      }

        先分析下zygote socket的创建。

//system/core/init/descriptors.cpp
52  void DescriptorInfo::CreateAndPublish(const std::string& globalContext) const {
53    // Create
54    const std::string& contextStr = context_.empty() ? globalContext : context_;
      //在/dev/socket目录下面创建文件一个文件
55    int fd = Create(contextStr);
56    if (fd < 0) return;
57  
      //这个key()为#define ANDROID_SOCKET_ENV_PREFIX "ANDROID_SOCKET_"
      //所以最终publish的全称为ANDROID_SOCKET_zygote
59    std::string publishedName = key() + name_;
60    std::for_each(publishedName.begin(), publishedName.end(),
61                  [] (char& c) { c = isalnum(c) ? c : '_'; });
62  
63    std::string val = std::to_string(fd);
      //将创建的socket的fd放入环境变量ANDROID_SOCKET_zygote中,此处要注意后面zygote进程中就是根据此来获取socket的fd的
64    setenv(publishedName.c_str(), val.c_str(), 1);
65  
66    // make sure we don't close on exec
67    fcntl(fd, F_SETFD, 0);
68  }

    socket的创建主要完成了两件事:

    1.创建一个socket fd,并且将这个fd与某个文件(dev/socket/xx,xx就是上面列出的名字,比如zygote)绑定,然后根据init.rc里面的定义来设定相关的用户,组合权限,最后返回fd。

    2.将socket名字(带ANDROID_SOCKET_前缀,比如ANDROID_SOCKET_zygote)和fd注册到init进程的环境变量里,这样所有其他进程(所有进程都是init的子进程)都可以通过getenv(name)获取fd。

    继续Start的流程,最后执行

if (!ExpandArgsAndExecv(args_, sigstop_)) {
    PLOG(ERROR) << "cannot execve('" << args_[0] << "')";
}

    这里会执行service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server正式开始zygote的启动。总结下以上流程:

                                                                        

3.Zygote进程启动

    从最开始分析的init.zygote64.rc可以看出,zygote64启动文件的地址为app_process64,app_process64对应的代码定义在frameworks/base/cmds/app_process中,可以看到该目录下对应的Android.mk

//frameworks/base/cmds/app_process/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 \
    ........
23 app_process_src_files := \
24     app_main.cpp \
    ........
45 LOCAL_MODULE:= app_process
    ........

    不管是app_process,app_process32还是app_process64对应的源文件都是app_main.cpp,其中的main函数就是zygote

进程启动的入口函数,整个启动过程的时序图如下:

                       

    zygote启动过程中主要完成以下工作:

    a.调用AndroidRuntime startVM()创建虚拟机

    b.调用startReg()注册JNI函数

    c.调用registerServerSocket建立socket通道,zygote作为服务端,用于响应客户端的请求。

    d.preload()预加载通用类,drawable和color资源,openGL以及共享库以及WebView,用于提升app的启动速度。

    e.startSystemServer创建system_server,以及各种系统进程。

    f.最后调用 (),通过while循环,一直监听接收client端创建新进程的请求。

    下面就按照时序图针对每一步骤进行详细介绍。

  1.main函数,init进程通过init_zygotexx.rc启动zygote进程,入口app_main.cpp

//frameworks/base/cmds/app_process/app_main.cpp
173  int main(int argc, char* const argv[])
//zygote传入的参数argv为"Xzygote /system/bin --zygote --start-system-server --socket-name=zygote"
174  {
175      if (!LOG_NDEBUG) {
176        String8 argv_String;
177        for (int i = 0; i < argc; ++i) {
178          argv_String.append("\"");
179          argv_String.append(argv[i]);
180          argv_String.append("\" ");
181        }
182        ALOGV("app_process main with argv: %s", argv_String.string());
183      }
184  
      ........
264      while (i < argc) {
265          const char* arg = argv[i++];
266          if (strcmp(arg, "--zygote") == 0) {
267              zygote = true;
                 //64位系统nice_name为zygote64,32位系统为zygote
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      }
      ........
285      if (!className.isEmpty()) {
286          // We're not in zygote mode, the only argument we need to pass
287          // to RuntimeInit is the application argument.
288          //
289          // The Remainder of args get passed to startup class main(). Make
290          // copies of them before we overwrite them with the process name.
291          args.add(application ? String8("application") : String8("tool"));
292          runtime.setClassNameAndArgs(className, argc - i, argv + i);
293  
294          if (!LOG_NDEBUG) {
295            String8 restOfArgs;
296            char* const* argv_new = argv + i;
297            int argc_new = argc - i;
298            for (int k = 0; k < argc_new; ++k) {
299              restOfArgs.append("\"");
300              restOfArgs.append(argv_new[k]);
301              restOfArgs.append("\" ");
302            }
303            ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string());
304          }
305      } else {
306          // We're in zygote mode.
             //进入zygote模式,新建Dalvik的缓存目录:/data/dalvik-cache
307          maybeCreateDalvikCache();
308  
309          if (startSystemServer) {
310              args.add(String8("start-system-server"));
311          }
312  
313          char prop[PROP_VALUE_MAX];
314          if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
315              LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
316                  ABI_LIST_PROPERTY);
317              return 11;
318          }
319  
320          String8 abiFlag("--abi-list=");
321          abiFlag.append(prop);
322          args.add(abiFlag);
323  
324          // In zygote mode, pass all remaining arguments to the zygote
325          // main() method.
326          for (; i < argc; ++i) {
327              args.add(String8(argv[i]));
328          }
329      }
330  
331      if (!niceName.isEmpty()) {
             //设置别名zygote/zygote64
332          runtime.setArgv0(niceName.string(), true /* setProcName */);
333      }
334  
335      if (zygote) {
             //如果是zygote模式,则加载ZygoteInit
336          runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
337      } else if (className) {
             //如果是application启动模式,则加载RuntimeInit
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      }
344  }

   2.start

//frameworks/base/core/jni/AndroidRuntime.cpp
1120  void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
1121  {
1122      ALOGD(">>>>>> START %s uid %d <<<<<<\n",
1123              className != NULL ? className : "(unknown)", getuid());
1124  
1125      static const String8 startSystemServer("start-system-server");
1126  
      ........
164      /* start the virtual machine */
1165      JniInvocation jni_invocation;
1166      jni_invocation.Init(NULL);
1167      JNIEnv* env;
          //创建虚拟机(时序图步骤3),详情见下步骤3
1168      if (startVm(&mJavaVM, &env, zygote) != 0) {
1169          return;
1170      }
1171      onVmCreated(env);
1172  
1173      /*
1174       * Register android functions.
1175       */
          //注册jni(时序图步骤4),详情见下步骤4
1176      if (startReg(env) < 0) {
1177          ALOGE("Unable to register all android natives\n");
1178          return;
1179      }
      ........
if (startClass == NULL) {
1211          ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
1212          /* keep going */
1213      } else {
              //反射调用ZygoteInit
1214          jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
1215              "([Ljava/lang/String;)V");//通过反射找到ZygoteInit.main()
1216          if (startMeth == NULL) {
1217              ALOGE("JavaVM unable to find main() in '%s'\n", className);
1218              /* keep going */
1219          } else {
                  //调用ZygoteInit的main函数,详情见下步骤5
1220              env->CallStaticVoidMethod(startClass, startMeth, strArray);
1221  
1222  #if 0
1223              if (env->ExceptionCheck())
1224                  threadExitUncaughtException(env);
1225  #endif
1226          }
1227      }
1228      free(slashClassName);
1229  
1230      ALOGD("Shutting down VM\n");
1231      if (mJavaVM->DetachCurrentThread() != JNI_OK)
1232          ALOGW("Warning: unable to detach main thread\n");
1233      if (mJavaVM->DestroyJavaVM() != 0)
1234          ALOGW("Warning: VM did not shut down cleanly\n");
1235  }

    start()函数主要完成3件事:

    a.调用startVm创建虚拟机

    b.调用startReg注册JNI方法

    c.启动Zygote进程

    每一步骤的详细分析如下:

    3.startVm

//frameworks/base/core/jni/AndroidRuntime.cpp
634  int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
     ........
         //jni检测功能,用于native层调用jni函数时进行常规检测
717      bool checkJni = false;
718      property_get("dalvik.vm.checkjni", propBuf, "");
719      if (strcmp(propBuf, "true") == 0) {
720          checkJni = true;
721      } else if (strcmp(propBuf, "false") != 0) {
722          /* property is neither true nor false; fall back on kernel parameter */
723          property_get("ro.kernel.android.checkjni", propBuf, "");
724          if (propBuf[0] == '1') {
725              checkJni = true;
726          }
727      }
728      ALOGV("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
729      if (checkJni) {
730          /* extended JNI checking */
731          addOption("-Xcheck:jni");
732  
733          /* with -Xcheck:jni, this provides a JNI function call trace */
734          //addOption("-verbose:jni");
735      }
         ........
         //preloaded-classes文件内容是有WriePreloadedClassFile.java生成的
         //预加载其中的classes提高系统性能
892      if (hasFile("/system/etc/boot-image.prof")) {
893          addOption("-Ximage-compiler-option");
894          addOption("--profile-file=/system/etc/boot-image.prof");
895          addOption("-Ximage-compiler-option");
896          addOption("--compiler-filter=speed-profile");
897      } else {
898          // Make sure there is a preloaded-classes file.
899          if (!hasFile("/system/etc/preloaded-classes")) {
900              ALOGE("Missing preloaded-classes file, /system/etc/preloaded-classes not found: %s\n",
901                    strerror(errno));
902              return -1;
903          }
904          addOption("-Ximage-compiler-option");
905          addOption("--image-classes=/system/etc/preloaded-classes");
906  
907          // If there is a dirty-image-objects file, push it.
908          if (hasFile("/system/etc/dirty-image-objects")) {
909              addOption("-Ximage-compiler-option");
910              addOption("--dirty-image-objects=/system/etc/dirty-image-objects");
911          }
912      }
        ........
          //初始化虚拟机
1079      if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
1080          ALOGE("JNI_CreateJavaVM failed\n");
1081          return -1;
1082      }
1083  
1084      return 0;
1085  }

    4.startReg

    startReg首先是设置了Android创建线程的处理函数,然后创建了一个200容量的局部引用域,用于确保不会出现OutMemoryException,最后调用register_jni_process进行JNI方法的注册。

//frameworks/base/core/jni/AndroidRuntime.cpp
1603  /*static*/ int AndroidRuntime::startReg(JNIEnv* env)
1604  {
1605      ATRACE_NAME("RegisterAndroidNatives");
1606      /*
1607       * This hook causes all future threads created in this process to be
1608       * attached to the JavaVM.  (This needs to go away in favor of JNI
1609       * Attach calls.)
1610       */
          //设置Android创建线程的函数javaCreateThreadEtc,这个函数内部是通过Linux的Clone创建线程的
1611      androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
1612  
1613      ALOGV("--- registering native functions ---\n");
1614  
1615      /*
1616       * Every "register" function calls one or more things that return
1617       * a local reference (e.g. FindClass).  Because we haven't really
1618       * started the VM yet, they're all getting stored in the base frame
1619       * and never released.  Use Push/Pop to manage the storage.
1620       */
          //创建一个200容量的局部引用域
1621      env->PushLocalFrame(200);
1622  
          //注册JNI,详情见下4.1
1623      if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
1624          env->PopLocalFrame(NULL);
1625          return -1;
1626      }
          //释放局部引用作用域
1627      env->PopLocalFrame(NULL);
1628  
1629      //createJavaThread("fubar", quickTest, (void*) "hello");
1630  
1631      return 0;
1632  }

    4.1 register_jni_procs

//frameworks/base/core/jni/AndroidRuntime.cpp
1407  static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
1408  {
1409      for (size_t i = 0; i < count; i++) {
1410          if (array[i].mProc(env) < 0) {//调用gRegJNI的mProc
1411  #ifndef NDEBUG
1412              ALOGD("----------!!! %s failed to load\n", array[i].mName);
1413  #endif
1414              return -1;
1415          }
1416      }
1417      return 0;
1418  }

//gRegJNI是一个全局数组,定义如下:
//frameworks/base/core/jni/AndroidRuntime.cpp
1420  static const RegJNIRec gRegJNI[] = {
1421      REG_JNI(register_com_android_internal_os_RuntimeInit),
1422      REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
1423      REG_JNI(register_android_os_SystemClock),
      ........

//frameworks/base/core/jni/AndroidRuntime.cpp
1392  #ifdef NDEBUG
1393      #define REG_JNI(name)      { name }
1394      struct RegJNIRec {
1395          int (*mProc)(JNIEnv*);
1396      };
1397  #else
1398      #define REG_JNI(name)      { name, #name }
1399      struct RegJNIRec {
1400          int (*mProc)(JNIEnv*);
1401          const char* mName;
1402      };
1403  #endif

    由此可见array[i].mProc,调用mProc就等价于其参数名所指向的函数,例如REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),就是调用register_com_android_internal_os_ZygoteInit_nativeZygoteInit

//frameworks/base/core/jni/AndroidRuntime.cpp
295  int register_com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env)
296  {
297      const JNINativeMethod methods[] = {
298          { "nativeZygoteInit", "()V",
299              (void*) com_android_internal_os_ZygoteInit_nativeZygoteInit },
300      };
         //和com/android/internal/os/ZygoteInit.java的nativeZygoteInit对应
301      return jniRegisterNativeMethods(env, "com/android/internal/os/ZygoteInit",
302          methods, NELEM(methods));
303  }

    5.反射调用ZygoteInit.main()

    main函数主要执行下面4个操作

    1.调用preload()预加载类和资源

    2.调用ZygoteServer()创建Server端的socket /dev/socket/zygote,Socket等待AMS请求Zygote来创建新的应用程序进程。

    3.调用forkSystemServer来启动SystemServer进程,接着SystemServer创建关键的系统进程。

    4.调用runSelectLoop等待客户端请求。

//frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
819      public static void main(String argv[]) {
        ........
873              if (!enableLazyPreload) {
874                  bootTimingsTraceLog.traceBegin("ZygotePreload");
875                  EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
876                          SystemClock.uptimeMillis());
                     //预加载类和资源,详情见5.1
877                  preload(bootTimingsTraceLog);
878                  EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
879                          SystemClock.uptimeMillis());
880                  bootTimingsTraceLog.traceEnd(); // ZygotePreload
881              } else {
882                  Zygote.resetNicePriority();
883              }
        ........
899  
                 //调用ZygoteServer构造函数,创建Server端socket,详情见5.2
900              zygoteServer = new ZygoteServer(isPrimaryZygote);
                 //启动systemServer,详情见5.3
902              if (startSystemServer) {
903                  Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
904  
905                  // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
906                  // child (system_server) process.
907                  if (r != null) {
908                      r.run();
909                      return;
910                  }
911              }
913              Log.i(TAG, "Accepting command socket connections");
914  
915              // The select loop returns early in the child process after a fork and
916              // loops forever in the zygote.
                 //zygote进入循环,等待client发出请求,详情见5.4
917              caller = zygoteServer.runSelectLoop(abiList);
918          } catch (Throwable ex) {
919              Log.e(TAG, "System zygote died with exception", ex);
920              throw ex;
921          } finally {
922              if (zygoteServer != null) {
923                  zygoteServer.closeServerSocket();
924              }
925          }
926  
927          // We're in the child process and have exited the select loop. Proceed to execute the
928          // command.
929          if (caller != null) {
930              caller.run();
931          }
932      }

    5.1 preload预加载

    为了让系统运行更流畅,一些系统中APP共享的资源会在zygote启动的时候进行预加载,这样在后面使用的时候就无需重复加载,加快了应用启动速度。Android通过zygote fork创建子进程,zygote进程预加载这些类和资源的时候,根据fork的copy-on-write机制可知,有些类如果不做改变,甚至不用复制。子进程可以和父进程共享这部分数据,从而省去不少内存的占用。

//frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
135      static void preload(TimingsTraceLog bootTimingsTraceLog) {
136          Log.d(TAG, "begin preload");
137          bootTimingsTraceLog.traceBegin("BeginPreload");
138          beginPreload();
139          bootTimingsTraceLog.traceEnd(); // BeginPreload
140          bootTimingsTraceLog.traceBegin("PreloadClasses");
             //预加载类,这些类记录在framework/base/preloaded-classes
141          preloadClasses();
142          bootTimingsTraceLog.traceEnd(); // PreloadClasses
143          bootTimingsTraceLog.traceBegin("CacheNonBootClasspathClassLoaders");
144          cacheNonBootClasspathClassLoaders();
145          bootTimingsTraceLog.traceEnd(); // CacheNonBootClasspathClassLoaders
146          bootTimingsTraceLog.traceBegin("PreloadResources");
             //加载图片,颜色等资源文件,部分定义在frameworks/base/ccore/res/res/values/array.xml
147          preloadResources();
148          bootTimingsTraceLog.traceEnd(); // PreloadResources
149          Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadAppProcessHALs");
150          nativePreloadAppProcessHALs();
151          Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
152          Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadGraphicsDriver");
153          maybePreloadGraphicsDriver();
154          Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
             //加载library
155          preloadSharedLibraries();
             //加载文字资源
156          preloadTextResources();
157          // Ask the WebViewFactory to do any initialization that must run in the zygote process,
158          // for memory sharing purposes.
             //初始化webview
159          WebViewFactory.prepareWebViewInZygote();
160          endPreload();
161          warmUpJcaProviders();
162          Log.d(TAG, "end preload");
163  
164          sPreloadComplete = true;
165      }

    5.2 创建server socket

    Android中采用LocalSocket,这是对Linux中Socket的封装,采用JNI方式调用,实现进程间通信。

    客户端:

    LocalSocket:客户端使用,创建套接字

    LocalSocketAddress:套接字地址,即文件描述符

    setSoTimeout:设置超时

    connect:客户端主动向服务端请求连接

    服务端:

    LocalServerSocket:服务端使用,创建套接字同时指定文件描述符

    accept:等待客户端连接

    架构示意图如下:

     

    

//frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
148      ZygoteServer(boolean isPrimaryZygote) {
149          mUsapPoolEventFD = Zygote.getUsapPoolEventFD();
150  
151          if (isPrimaryZygote) {
                 //创建socket,并获取socket对象,socket name:zygote
152              mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
                 //创建socket,并获取socket对象,socket name:usap_pool_primary
153              mUsapPoolSocket =
154                      Zygote.createManagedSocketFromInitSocket(
155                              Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
156          } else {
157              mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
158              mUsapPoolSocket =
159                      Zygote.createManagedSocketFromInitSocket(
160                              Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
161          }
162  
163          fetchUsapPoolPolicyProps();
164  
165          mUsapPoolSupported = true;
166      }
//frameworks/base/core/java/com/android/internal/os/Zygote.java
161      private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";

858      static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
859          int fileDesc;
             //fullSocketName为ANDROID_SOCKET_zygote,注意这个名字和我们
             //DescriptorInfo::CreateAndPublish注册的名字一致
860          final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
861  
862          try {
                 //init.zygote64.rc启动时注册了2个socket,分别是zygote,
                 //usap_pool_primary,在进程创建时会创建对应的文件描述符并加入到环境变量,
                 //这边根据name将它们取出
863              String env = System.getenv(fullSocketName);
864              fileDesc = Integer.parseInt(env);
865          } catch (RuntimeException ex) {
866              throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
867          }
868  
869          try {
870              FileDescriptor fd = new FileDescriptor();
871              fd.setInt$(fileDesc);//获取zygote socket的文件描述符
872              return new LocalServerSocket(fd);//创建socket的服务端
873          } catch (IOException ex) {
874              throw new RuntimeException(
875                  "Error building socket from file descriptor: " + fileDesc, ex);
876          }
877      }


//frameworks/base/core/java/android/net/LocalServerSocket.java
63      public LocalServerSocket(FileDescriptor fd) throws IOException
64      {
65          impl = new LocalSocketImpl(fd);
66          impl.listen(LISTEN_BACKLOG);
67          localAddress = impl.getSockAddress();
68      }

     Socket Server端工作完成,等待client端的connect连接。

    5.3启动SystemServer

//frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
724      private static Runnable forkSystemServer(String abiList, String socketName,
725              ZygoteServer zygoteServer) {
726          long capabilities = posixCapabilitiesAsBits(
727                  OsConstants.CAP_IPC_LOCK,
728                  OsConstants.CAP_KILL,
729                  OsConstants.CAP_NET_ADMIN,
730                  OsConstants.CAP_NET_BIND_SERVICE,
731                  OsConstants.CAP_NET_BROADCAST,
732                  OsConstants.CAP_NET_RAW,
733                  OsConstants.CAP_SYS_MODULE,
734                  OsConstants.CAP_SYS_NICE,
735                  OsConstants.CAP_SYS_PTRACE,
736                  OsConstants.CAP_SYS_TIME,
737                  OsConstants.CAP_SYS_TTY_CONFIG,
738                  OsConstants.CAP_WAKE_ALARM,
739                  OsConstants.CAP_BLOCK_SUSPEND
740          );
741          /* Containers run without some capabilities, so drop any caps that are not available. */
742          StructCapUserHeader header = new StructCapUserHeader(
743                  OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
744          StructCapUserData[] data;
745          try {
746              data = Os.capget(header);
747          } catch (ErrnoException ex) {
748              throw new RuntimeException("Failed to capget()", ex);
749          }
750          capabilities &= ((long) data[0].effective) | (((long) data[1].effective) << 32);
751  
752          /* Hardcoded command line to start the system server */
753          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 */
                 //通过fork分裂出子进程system_server
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();
                 //system server处理函数
798              return handleSystemServerProcess(parsedArgs);
799          }
800  
801          return null;
802      }

    关于SystemServer的启动我们会在后面用单独一篇博客来介绍。

    5.4 runSelectLoop等待client端请求

    创建出SystemServer进程后,zygote进程调用ZygoteServer中的runSelectLoop处理server socket收到的请求。

//frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
373      Runnable runSelectLoop(String abiList) {
374          ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>();
375          ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
376  
377          socketFDs.add(mZygoteSocket.getFileDescriptor());
378          peers.add(null);
379  
             //无限循环用来等待AMS请求Zygote创建新的应用进程
380          while (true) {
        ........
431              try {
                     //轮询,处理pollFDs事件
432                  Os.poll(pollFDs, -1);
433              } catch (ErrnoException ex) {
434                  throw new RuntimeException("poll failed", ex);
435              }
436  
437              boolean usapPoolFDRead = false;
438  
439              while (--pollIndex >= 0) {
440                  if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
441                      continue;
442                  }
443  
444                  if (pollIndex == 0) {
445                      // Zygote server socket
446                      //客户端发出连接请求,调用server socket端的accpet函数。Zygote进程与AMS进程建立了连接
447                      ZygoteConnection newPeer = acceptCommandPeer(abiList);
448                      peers.add(newPeer);
449                      socketFDs.add(newPeer.getFileDescriptor());
450  
451                  } else if (pollIndex < usapPoolEventFDIndex) {
                         //AMS向zygote发出创建新进程的请求
452                      // Session socket accepted from the Zygote server socket
453  
454                      try {
455                          ZygoteConnection connection = peers.get(pollIndex);
                             //创建新的应用程序进程
456                          final Runnable command = connection.processOneCommand(this);
        ........
//frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
129      Runnable processOneCommand(ZygoteServer zygoteServer) {
        ........
            //fork 子进程
67          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);
        ........

    应用进程的创建后面我们也会用单独的一篇博客来说明,本篇博客更多的是梳理zygote进程的启动流程。至此zygote进程的启动全部结束。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值