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-server socket zygote stream 660创建一个名为:/dev/socket/zygote 的 socket, 类型为:stream,权限为:660 onrestart:当服务重启时,执行该关键字后面指定的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 NAME root 1 0 688 328 c011bda0 00010be4 S /init root 156 1 537700 23488 ffffffff 400d1d40 S zygote system 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的启动序列图如下:
- 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的创建流程。
总结
- 系统启动时init进程会创建Zygote进程,Zygote进程负责后续Android应用程序框架层的其它进程的创建和启动工作
- Zygote进程会首先创建一个SystemServer进程,SystemServer进程负责启动系统的关键服务,如包管理服PackageManagerService和应用程序组件管理服务ActivityManagerService。
- 当我们需要启动一个Android应用程序时,ActivityManagerService会通过Socket进程间通信机制,通知Zygote进程为这个应用程序创建一个新的进程
- 启动zygote,进入Java世界
- zygote分裂出第一个进程system_server
- Zygote服务端监听fork子进程请求