Android系统启动(三)-Zygote篇

2018-11-05  本文已影响52人  Stan_Z

在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(&mJavaVM, &env, zygote)
    
     startReg(env)
     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( )方法中主要工作:

整体流程时序图如下:

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. zygote完毕大部分工作,接下来再通过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应用程序进程为例:

from gityuan

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

上一篇下一篇

猜你喜欢

热点阅读