Zygote进程详解

来源:互联网 发布:c语言 char负值 编辑:程序博客网 时间:2024/06/05 15:31

Zygote进程是怎么启动的?

  • Android系统是基于Linux内核的,而在Linux系统中,所有的进程都是init进程的子孙进程,也就是说,所有的进程都是直接或者间接地由init进程fork出来的。Zygote进程也不例外,它是在系统启动的过程,由init进程创建的。
  • 在system\core\rootdir\init.rc文件中可以看到zygote的如下信息;
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server    class main    socket zygote stream 660 root system    onrestart write /sys/android_power/request_state wake    onrestart write /sys/power/state on    onrestart restart media    onrestart restart netd服务名称为:zygote启动该服务执行的命令: /system/bin/app_process命令的参数: -Xzygote /system/bin –zygote –start-system-serversocket zygote stream 660创建一个名为:/dev/socket/zygote 的 socket,类型为:stream,权限为:660onrestart:当服务重启时,执行该关键字后面指定的command总结:zygote要执行的程序便是system/bin/app_process,它的源代码在frameworks/base/cmds/app_process/app_main.cpp问题:可执行文件app_process运行后,通过ps验证其进程名为zygote,是如何转换的呢?解答:init.rc中定义中,参数为-Xzygote
  • 通过adb shell ps |egrep '\<init\>|zygote|system_server' 命令可以查看到init,zygote,system_server之间的关系;
USER     PID   PPID  VSIZE  RSS     WCHAN    PC         NAMEroot      1     0     688    328   c011bda0 00010be4 S /initroot      156   1     537700 23488 ffffffff 400d1d40 S zygotesystem    670   156   744476 75312 ffffffff 400d1c90 S system_serve
  • init除了将zggote启动外,servicemanager、vold、rild、surfaceflinger等关键进程也都是通过init进程启动的


Zygote进程执行流程

  • Zygote进程执行流程
1.zygote进程是运行的app_process,app_process在frameworks/base/cmds/app_process/下,程序的入口为该目录下app_main.cpp文件的main函数。2.在main函数中,会创建一个AppRuntime(AppRuntime是继承于AndroidRuntime)变量,然后调用它的start方法;  runtime.start("com.android.internal.os.ZygoteInit",startSystemServer ? "start-system-server" : "");  在init.rc中,zygote service设置了--start-system-server参数,因此startSystemServer为true;3.调用AndroidRuntime的start方法,在这个方法里主要做了三件事情:  (1).AndroidRuntime::startVm()中,设置一些虚拟机的参数后,通过JNI_CreateJavaVM()启动虚拟机;  (2).调用函数startReg注册JNI方法;  (3).env->CallStaticVoidMethod,调用com.android.internal.os.ZygoteInit类的main()方法,正式进入到Java世界4.在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java的main函数中,做了三件事情:  (1).调用registerZygoteSocket函数,创建了一个socket接口,用来和ActivityManagerService通信;      <1>.registerZygoteSocket函数创建的socket接口是通过文件描述符(代表/dev/socket/zygote)来创建的;          private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote" (环境变量)          String env = System.getenv(ANDROID_SOCKET_ENV);          int fileDesc = Integer.parseInt(env);          sServerSocket = new LocalServerSocket(createFileDescriptor(fileDesc));      <2>.在init.c中service_start函数用于解析service命令,每一个service命令都会促使init进程调用fork函数来创建一个新的进程;          在新的进程里,都会通过create_socket(si->name, socket_type,si->perm, si->uid, si->gid);函数在/dev/socket目录下创建一个文件;          然后调用publish_socket(si->name, s);方法将描述符写到环境变量ANDROID_SOCKET_ENV中去  (2).调用startSystemServer函数来启动SystemServer组件;  (3).调用runSelectLoopMode(在4.4上为runSelectLoop)函数,进入一个无限循环,便于在前面创建的socket接口上等待ActivityManagerService请求创建新的进程;5.startSystemServer函数中,调用Zygote.forkSystemServer函数来创建一个新进程来启动SystemServer组件;  pid = Zygote.forkSystemServer(          parsedArgs.uid, parsedArgs.gid,          parsedArgs.gids,          parsedArgs.debugFlags,          null,          parsedArgs.permittedCapabilities,          parsedArgs.effectiveCapabilities);  // For child process  if (pid == 0) {     handleSystemServerProcess(parsedArgs);//新创建都进程都会执行  }6.在handleSystemServerProcess函数中,会调用closeServerSocket关闭socket描述符,接着调用RuntimeInit.zygoteInit函数来进一步启动SystemServer组件的操作;  子进程继承zygote的socket文件描述符,但用不到,因此会调用closeServerSocket关闭socket描述符;7.在RuntimeInit(frameworks/base/core/java/com/android/internal/os/RuntimeInit.java).zygoteInit函数中会执行两个操作:  (1).调用nativeZygoteInit函数来执行一个Binder进程间通信机制的初始化工作;  (2).会依次调用applicationInit(targetSdkVersion, argv);->invokeStaticMain(args.startClass, args.startArgs);函数,并抛出ZygoteInit.MethodAndArgsCaller异常;8.抛出的ZygoteInit.MethodAndArgsCaller异常会被ZygoteInit 的main函数捕获,调用caller.run();  在run方法中将调用com.android.server.SystemServer类中的main方法;  SystemServer类:frameworks/base/services/java/com/android/server/SystemServer.java
  • Zygote的启动序列图如下:

Android System Train Note Android Zygote Start.gif

  • system_server是Zygote的分裂出的第一个子进程,即PPID为156(zygote的pid)的所有进程中他的PID编号最小


Zygote的监听和处理

  • 在上面的第三步中,调用runSelectLoopMode(在4.4上为runSelectLoop)函数,进入一个无限循环,便于在前面创建的socket接口上等待ActivityManagerService请求创建新的进程;
  • runSelectLoop函数中关键代码如下:
while (true) {    try {        fdArray = fds.toArray(fdArray);        index = selectReadable(fdArray); //多路Select,响应Socket请求    } catch (IOException ex) {        throw new RuntimeException("Error in select()", ex);    }}
  • 接收到Socket请求后,会fork出子进程,子进程调用handleChildProc方法,最终抛出RuntimeInit.invokeStaticMain异常,退出while(true)循环,进入到android.app.ActivityThread类的main方法执行;父进程调用handleParentProc方法,再次进入runSelectLoopMode中while(true)循环,准备接收下一个的请求事件。
  • 和启动system_server进程时的调用堆栈非常相似,ZygoteInit类中的main方法中捕获MethodAndArgsCaller异常,并调用异常对象的run方法。即android.app.ActivityThread类的main方法,开始Activity的创建流程。


总结

  1. 系统启动时init进程会创建Zygote进程,Zygote进程负责后续Android应用程序框架层的其它进程的创建和启动工作
  2. Zygote进程会首先创建一个SystemServer进程,SystemServer进程负责启动系统的关键服务,如包管理服PackageManagerService和应用程序组件管理服务ActivityManagerService。
  3. 当我们需要启动一个Android应用程序时,ActivityManagerService会通过Socket进程间通信机制,通知Zygote进程为这个应用程序创建一个新的进程


  • 启动zygote,进入Java世界

Android System Train Note Android Zygote 001.jpg 

  • zygote分裂出第一个进程system_server

Android System Train Note Android Zygote 002.jpg 

  • Zygote服务端监听fork子进程请求

Android System Train Note Android Zygote 003.jpg

0 0
原创粉丝点击