Android系统启动(三)-Zygote篇

在Android系统中,Zygote是java进程的鼻祖。它在启动时会创建虚拟机,并通过fork(复制进程)的形式来创建应用程序进程和SystemServer进程。

一、Zygote启动流程

从上篇文章得知init启动Zygote时主要是调用app_main.cpp的main函数中的AppRuntime的start来启动zygote进程的,我们就从app_main.cpp的main函数开始分析。

1.1 AndroidRuntime.cpp

AppRuntime声明在app_main.cpp中,它继承AndroidRuntime,也就是我们调用start其实是调用AndroidRuntime的start函数。
frameworks/base/core/jni/AndroidRuntime.cpp start( )方法中主要工作:

  • 调用startVm函数来创建JavaVm(DVM),并通过调用startReg函数用来为DVM注册JNI
     startVm(&mJavaVM, &env, zygote)
    
     startReg(env)
  • 找到ZygoteInit的main函数,并通过JNI调用,自此Zygote便进入了Java框架层。
     jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
     "([Ljava/lang/String;)V”);

     env->CallStaticVoidMethod(startClass, startMeth, strArray);
1.2 ZygoteInit.java

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java main( )方法中主要工作:

  • 注册Zygote用的Socket,当Zygote进程将SystemServer进程启动后,就会在这个服务端的Socket上来等待ActivityManagerService请求Zygote进程来创建新的应用程序进程。

       registerZygoteSocket(socketName);
    
  • 预加载的资源、类、虚拟机实例等。

      preload();
    
  • 启动SystemServer进程,该进程承载着framework的核心服务。

       startSystemServer(abiList, socketName);
    
  • 循环等待并处理AMS发送来的创建新应用进程请求。如果收到创建应用程序的请求,则调用ZygoteConnection的runOnce函数来创建一个新的应用程序进程。

      runSelectLoop(abiList);
    

整体流程时序图如下:

Android系统启动(三)-Zygote篇_第1张图片
from gityuan

Zygote进程启动总结:
  1. 解析init.zygote.rc中的参数,创建AppRuntime并调用AppRuntime.start()方法,实际调用AndroidRuntime.start(), 通过startVM()方法创建虚拟机,再调用startReg()注册JNI函数;
  2. 通过JNI方式调用ZygoteInit.main(),第一次进入Java世界;
  3. registerZygoteSocket()建立socket通道,zygote作为通信的服务端,用于响应客户端请求;
  4. preload()预加载通用类、drawable和color资源、openGL以及共享库以及WebView,用于提高app启动效率;
  5. 通过startSystemServer(),fork得力帮手system_server进程,也是上层framework系统服务的运行载体。
  6. zygote功成身退,调用runSelectLoop(),随时待命,当接收到请求创建新进程请求时立即唤醒并执行相应工作。
  7. 同时会因为surfaceflinger、servicemanager、system_server进程被杀而被动触发Zygote重启。
  8. 对于Android 5.0以上系统,有两个zygote进程,分别是zygote、zygote64两个进程,从名字可以看出分别对应32位和64位,但是确实是都创建了。
    mido:/ # ps | grep zygote
     root      714   1     2176388 47548 poll_sched 7faf1bd660 S zygote64 
     root      715   1     1613320 35496 poll_sched 00f292e3f4 S zygote
    

二、copy-on-write fork了解一下

linux为了提高 fork 的效率,采用了 copy-on-write 技术,从父进程fork一个子进程,刚fork之后,这两个虚拟地址实际上指向的是相同的物理地址(内存页),且把父子共享的页面标记为“只读”,但如果其中任何一个进程要对共享的页面“写操作”,这时内核会复制一个物理页面给这个进程使用,同时修改页表,把原来的只读页面标记为“可写”,留给另外一个进程使用。此时两个虚拟地址指向不同的物理地址(新的物理地址的内容从原物理地址中复制得到)。

以Zygote进程fork应用程序进程为例:

Android系统启动(三)-Zygote篇_第2张图片
from gityuan

Zygote进程地址空间中包含有预加载资源、预加载类、虚拟机实例等。当Zygote fork一个应用程序进程时,父子进程先是共享相同物理地址资源,但是仅仅只能读不能写,如果此时应用进程开始写操作,那么会从Zygote原物理地址中复制内容到一块新的物理地址上,供应用程序进程使用。这样子进程可以高效而完整地继承父进程内存地址中的数据。

系列文章:
Android系统启动(一)-开篇
Android系统启动(二)-Init篇
Android系统启动(三)-Zygote篇
Android系统启动(四)-SystemServer篇
Android系统启动(五)-ActivityManagerService篇
Android系统启动(六)-Launcher篇

你可能感兴趣的:(Android系统启动(三)-Zygote篇)