【Android话题-2.1系统服务】谈谈你对zygote的理解

Source

这道题想考察什么?

  • 了解Zygote的作用(初级)
  • 熟悉Zygote的启动流程(中级)
  • 深刻理解Zygote的工作原理(高级)

---------------------------------------------------------------------------------

【Zygote的作用】

  • 启动SystemServer
  • 孵化应用进程

(SystemServer用到Zygote准备的资源:常用类、JNI函数、主题资源、共享库)

启动三段式:进程启动 => 准备工作 => LOOP

【Zygote的启动流程】

  • init进程fork出zygote进程;——(用execve{Zygote可执行文件的路径})
  • 启动虚拟机、注册jni函数;
  • 预加载系统资源;——(常用类、JNI函数、主题资源、共享库等,为为孵化应用进程作准备)
  • 启动SystemServer;
  • 进程Socket Loop

(其中前两点在Native中执行,后三点在Java中执行)

【深刻理解Zygote的工作原理】

Native是如何切换到Java的?实验代码:

int main(int argc, char *argv[]){
  JavaVM *jvm;
  JNIEnv *env;
  JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args);
  jclass class = env->FindClass("ZygoteInit");
  jmethodID method = env->GetStaticMethodID(class, "Main", "([Ljava/lang/String;)V");
  env->CallStaticVoidMethod(clazz, method, args);
  jvm->DestroyJavaVM();
}

SystemServer是如何跟Zygote通信的?

  • SystemServer通过Socket与Zygote通信
  • Zygote处理SystemServer发来的请求(请求通常是创建新进程并调用ActivityThread.main())

Zygote处理请求的关键代码:

boolean runOnce(){
  //读取参数列表,是AMS跨进程发过来的
  String[] args = readArgumentList();
  //根据参数启动子进程
  int pid = Zygote.forkAndSpecialize();
  //在子进程中干活:执行Java类的main函数,java类名来自上面读取的参数列表
  //其实类名就是ActivityThread
  if(pid == 0){
    //in child
    //由上可知ActivityThread.main()
    handleChildProc(args, ...);
    return true;
  }
}

要注意的细节:

  • Zygote fork要单线程 (否则可能会莫名死锁或者状态不一致)
  • Zygote的IPC没有采用binder (而是用本地Socket)

【遗留两个问题】:

  • 孵化应用进程这种事为什么不交给SystemServer来做,而专门设计一个Zygote?
  • Zygote的 IPC通信机制为什么不采用binder?如果采用binder的话会有什么问题?

 

---------------------------------------------------------------------------------------------------------------------

【Zygote启动源码分析】

init.zygote64.rc启动脚本:

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks
  • 这个脚本由init进程解析
  • 根据该脚本init将fork一个进程,新进程将运行/system/bin/app_process64
  • app_process64的入口函数是/framework/base/cmds/app_process/app_main.cpp::main()

CPP部分:

app_main.cpp::main(){
  //创建/data/dalvik-cache/arm64 目录
  maybeCreateDalvikCache() 
  AndroidRuntime.cpp::start("com.android.internal.os.ZygoteInit", ...){
    AndroidRuntime.cpp::startVm()
    app_main.cpp::AppRuntime.cpp.onVmCreated(){
    }
    //找到并调用com.android.internal.os.ZygoteInit中的main()方法
    char* slashClassName = toSlashClassName("com.android.internal.os.ZygoteInit");
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V");
    env->CallStaticVoidMethod(startClass, startMeth, strArray);
}}
  •  启动虚拟机
  • 调用/framework/base/core/java/com/android/internal/os/ZygoteInit.java::main(),从此进入Java世界

Java部分:

ZygoteInit.java.main(){
  //if (startSystemServer):
  //P1.1: 启动SystemServer
  Runnable r = ZygoteInit.java::forkSystemServer(abiList, socketName, zygoteServer){
    Zygote.forkSystemServer()
    //pid == 0:
    ZygoteInit.java::handleSystemServerProcess(){
      //P5: 将SystemServer.class传给zygoteInit
      ZygoteInit.java::zygoteInit(){
        RuntimeInit.commonInit();
        ZygoteInit.nativeZygoteInit();
        RuntimeInit.applicationInit(){
          RuntimeInit.java::findStaticMain(){
            //main方法
            cl = Class.forName(className, true, classLoader);
            m = cl.getMethod("main", new Class[] { String[].class });
            new MethodAndArgsCaller(){
            //mThread 将保存main()方法
  }}}}}}
  //MethodAndArgsCaller.run
  r.run(){
    //实际调用的是SystermServer.java::main()方法
    mMethod.invoke(null, new Object[] { mArgs });
  }
----------------------------------------------------------
  //else:
  //P1.2: 启动应用进程
  caller = ZygoteServer.java::runSelectLoop(){
    //一直等待SystemServer的请求
    while(true):
      ZygoteConnection.java::processOneCommand(){
        //读取参数列表
        readArgumentList();
        //创建新进程
        pid = Zygote.forkAndSpecialize(……)
        if pid == 0:
          //子进程的处理
          handleChildProc(){
            //P6: 与P5类似,将ActivityThread .class传给zygoteInit
            ZygoteInit.java::zygoteInit()
          }
        else:
          //父进程:也就是Zygote
          handleParentProc(){
          }
  }
  //MethodAndArgsCaller.run:
  caller.run(){
    //实际调用的是ActivityThread.java::main()方法
    mMethod.invoke(null, new Object[] { mArgs });
  }
}

 

发布了101 篇原创文章 · 获赞 27 · 访问量 10万+