Zygote, 意为“受精卵”,Android系统中几乎所有的应用进程都是由Zygote进程孵化出来的,Java环境也是由Zygote创建起来的,它建立了我们app运行所需要的环境,是app的祖先,因此,分析它的启动以及内部逻辑显得非常有必要。

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  socket zygote stream 666   # zygote需要一个套接字onrestart write /sys/android_power/request_state wake  # zygote重启的话,需要执行这个操作onrestart write /sys/power/state on  onrestart restart media  onrestart restart netd

上述脚本表示要启动一个进程,名称为zygote, 可执行文件为/system/bin/app_process, --Xzygote /system/bin --zygote --start-system-server这些是传给zygote的参数,其余部分的作用见注释。

app_process对应的源码在frameworks/base/cmds/app_process目录下,其入口函数main在文件app_main.cpp中,接下来我们就从这个main函数入手来分析zygote的内部逻辑。

注意: 本文的源码分析基于Android 4.4。

/*
* 启动zygote的方式为/system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
* 所以 argc == 5
*      argv里头存的就是这5个参数argv[0]=="/system/bin/app_process" ,argv[1] == "-Xzygote"....
*/
int main(int argc, char* const argv[])
{......// These are global variables in ProcessState.cppmArgC = argc;mArgV = argv;mArgLen = 0;for (int i=0; i<argc; i++) {mArgLen += strlen(argv[i]) + 1;}mArgLen--;// 以上代码主要是将参数相关信息保存到全局变量中AppRuntime runtime;const char* argv0 = argv[0];// Process command line arguments// ignore argv[0]argc--;argv++;// Everything up to '--' or first non '-' arg goes to the vmint i = runtime.addVmArguments(argc, argv); // 这个函数会返回1,表示只处理了-Xzytote这一个参数,所谓的处理实际上就是将这个参数添加到了runtime对象的mOptions 变量中。// Parse runtime arguments.  Stop at first unrecognized option.bool zygote = false;bool startSystemServer = false;bool application = false;const char* parentDir = NULL;const char* niceName = NULL;const char* className = NULL;// 进入循环之前 i == 1, argc == 4  argv 指向“-Xzygote” while (i < argc) {const char* arg = argv[i++];if (!parentDir) {parentDir = arg;  // parentDir被赋值为"/system/bin"} else if (strcmp(arg, "--zygote") == 0) {  zygote = true;niceName = "zygote"; // 进程名} else if (strcmp(arg, "--start-system-server") == 0) {startSystemServer = true;} else if (strcmp(arg, "--application") == 0) { // 不走这个分支application = true;} else if (strncmp(arg, "--nice-name=", 12) == 0) {  // 不走这个分支niceName = arg + 12;} else {  // 不走这个分支className = arg;break;}}if (niceName && *niceName) {  // 设置进程名setArgv0(argv0, niceName);set_process_name(niceName);}runtime.mParentDir = parentDir;if (zygote) { // 走这个分支runtime.start("com.android.internal.os.ZygoteInit",startSystemServer ? "start-system-server" : "");} else if (className) {// Remainder of args get passed to startup class main()runtime.mClassName = className;runtime.mArgC = argc - i;runtime.mArgV = argv + i;runtime.start("com.android.internal.os.RuntimeInit",application ? "application" : "tool");} else {fprintf(stderr, "Error: no class name or --zygote supplied.\n");app_usage();LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");return 10;}
}

main函数主要就是创建了runtime实例,并且解析参数,然后调用runtime的start函数,接着我们分析AppRuntime的start函数:

/** Start the Android runtime.  This involves starting the virtual machine* and calling the "static void main(String[] args)" method in the class* named by "className".** Passes the main function two arguments, the class name and the specified* options string.*/// 首先我们明确下传进来的参数  className == "com.android.internal.os.ZygoteInit"  options == "start-system-server"
void AndroidRuntime::start(const char* className, const char* options)
{ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",className != NULL ? className : "(unknown)");/** 'startSystemServer == true' means runtime is obsolete and not run from* init.rc anymore, so we print out the boot start event here.*/if (strcmp(options, "start-system-server") == 0) {/* track our progress through the boot sequence */const int LOG_BOOT_PROGRESS_START = 3000;LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));}const char* rootDir = getenv("ANDROID_ROOT");if (rootDir == NULL) {rootDir = "/system";if (!hasDir("/system")) {LOG_FATAL("No root directory specified, and /android does not exist.");return;}setenv("ANDROID_ROOT", rootDir, 1);  //配置ANDROID_ROOT环境变量}//const char* kernelHack = getenv("LD_ASSUME_KERNEL");//ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);/* start the virtual machine */JniInvocation jni_invocation;jni_invocation.Init(NULL);JNIEnv* env;if (startVm(&mJavaVM, &env) != 0) { // 创建虚拟机return;}onVmCreated(env);/** Register android functions.*/if (startReg(env) < 0) {ALOGE("Unable to register all android natives\n");return;}/** We want to call main() with a String array with arguments in it.* At present we have two arguments, the class name and an option string.* Create an array to hold them.*/jclass stringClass;jobjectArray strArray;jstring classNameStr;jstring optionsStr;stringClass = env->FindClass("java/lang/String");assert(stringClass != NULL);strArray = env->NewObjectArray(2, stringClass, NULL);assert(strArray != NULL);classNameStr = env->NewStringUTF(className);assert(classNameStr != NULL);env->SetObjectArrayElement(strArray, 0, classNameStr);optionsStr = env->NewStringUTF(options);env->SetObjectArrayElement(strArray, 1, optionsStr);/** Start VM.  This thread becomes the main thread of the VM, and will* not return until the VM exits.*/char* slashClassName = toSlashClassName(className);jclass startClass = env->FindClass(slashClassName);if (startClass == NULL) {ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);/* keep going */} else {jmethodID startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");if (startMeth == NULL) {ALOGE("JavaVM unable to find main() in '%s'\n", className);/* keep going */} else {/* 调用com.android.internal.os.ZygoteInit的main函数,strArray是参数,数组里面有两个元素,className == "com.android.internal.os.ZygoteInit"  options == "start-system-server" */env->CallStaticVoidMethod(startClass, startMeth, strArray);#if 0if (env->ExceptionCheck())threadExitUncaughtException(env);
#endif}}free(slashClassName);ALOGD("Shutting down VM\n");if (mJavaVM->DetachCurrentThread() != JNI_OK)ALOGW("Warning: unable to detach main thread\n");if (mJavaVM->DestroyJavaVM() != 0)ALOGW("Warning: VM did not shut down cleanly\n");
}

start函数主要做了以下几件事情:

  1. 调用startVm函数创建虚拟机;
  2. 调用startReg函数注册Android Natvie函数;
  3. 让虚拟机去执行com.android.internal.os.ZygoteInit的main函数。

接下来我们分析下com.android.internal.os.ZygoteInit的main函数, 创建虚拟机以及注册native函数的过程后续再分析。

public static void main(String argv[]) {try {// Start profiling the zygote initialization.SamplingProfilerIntegration.start();registerZygoteSocket();  // 1、创建一个套接字,用于监听ams发过来的fork请求EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,SystemClock.uptimeMillis());preload(); // 2、加载classes 和resources, 后面会详细分析EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,SystemClock.uptimeMillis());// Finish profiling the zygote initialization.SamplingProfilerIntegration.writeZygoteSnapshot();// Do an initial gc to clean up after startupgc();// If requested, start system server directly from Zygoteif (argv.length != 2) {throw new RuntimeException(argv[0] + USAGE_STRING);}if (argv[1].equals("start-system-server")) {startSystemServer(); //3、 创建system server进程,ams wms pms等常见service都在该进程里面} else if (!argv[1].equals("")) {throw new RuntimeException(argv[0] + USAGE_STRING);}Log.i(TAG, "Accepting command socket connections");if (ZYGOTE_FORK_MODE) {runForkMode();} else {runSelectLoopMode(); // 4、进入循环监听模式,监听外来请求}closeServerSocket();} catch (MethodAndArgsCaller caller) {caller.run();} catch (RuntimeException ex) {Log.e(TAG, "Zygote died with exception", ex);closeServerSocket();throw ex;}}

com.android.internal.os.ZygoteInit的main函数主要做了四件事情:

  1. 调用registerZygoteSocket()创建一个套接字,用于监听ams发过来的fork请求;
  2. 调用preload()预加载classes 和resources;
  3. 调用startSystemServer()创建system server进程,ams wms pms等常见service都在该进程里面;
  4. 调用runSelectLoopMode()进入循环监听模式,监听外来请求。

Android Zygote进程启动过程相关推荐

  1. 从源码角度看Android系统Zygote进程启动过程

    在Android系统中,DVM.ART.应用程序进程和SystemServer进程都是由Zygote进程创建的,因此Zygote又称为"孵化器".它是通过fork的形式来创建应用程 ...

  2. Android系统启动(二) — Zygote进程启动过程

    1 概述 在 Android 系统中,DVM(Dalvik 虚拟机)和 ART,系统服务进程 system_server 以及应用程序进程都是由 Zygote 进程来创建的(而 Native 程序,也 ...

  3. Android 系统(12)---Zygote进程启动过程

    android系统进程启动流程 android系统的Zygote进程是所有android进程的父进程,包括SystemServer和各种应用进程都是通过Zygote进程fork出来的.Zygote(孵 ...

  4. Zygote进程启动过程源代码分析

    Zygote进程介绍 在Android系统中,存在不同的服务,这些服务可以分为: Android系统借用Binder通信机制实现了C/S架构设计,客户端应用程序如需要实现某些功能,只需请求指定的服务, ...

  5. Zygote进程启动过程

    1.Zygote简介 在Android系统中,DVM(Dalvik虚拟机).应用程序进程以及运行系统关键服务的SystemServer进程都是由Zygote进程来创建的,我们也将它称为孵化器.它通过f ...

  6. Android应用程序进程启动过程

    相关文章 Android系统架构与系统源码目录 Android系统启动流程(一)解析init进程启动过程 Android系统启动流程(二)解析Zygote进程启动过程 Android系统启动流程(三) ...

  7. 从源码角度看Android系统SystemServer进程启动过程

    SystemServer进程是由Zygote进程fork生成,进程名为system_server,主要用于创建系统服务. 备注:本文将结合Android8.0的源码看SystemServer进程的启动 ...

  8. Android 系统(14)---SystemServer进程启动过程

    SystemServer进程的启动 在上一篇文章Framework学习(二)Zygote进程启动过程中,我们已经知道Zygote进程会启动SystemServer进程,但具体启动流程还没有涉及,本文我 ...

  9. [日更-2019.4.26、27、28] cm-14.1 Android系统启动过程分析(四)-应用程序进程启动过程...

    2019独角兽企业重金招聘Python工程师标准>>> 声明 前阶段在项目中涉及到了Android系统定制任务,Android系统定制前提要知道Android系统是如何启动的: 本文 ...

最新文章

  1. 云从完成超过18亿元新一轮融资,加快上市步伐
  2. 有道python网课怎么样-如何用python“优雅的”调用有道翻译?
  3. 数学在机器学习中的作用
  4. 创新创业计划书_创践——大学生创新创业实务 ——如何撰写一份优秀的商业计划书...
  5. 微软 azure_在Microsoft Azure上运行Eclipse MicroProfile
  6. 向其他进程注入代码的三种方法
  7. linux-文件管理-不完整版
  8. 【POJ16553107】树的重心——点分治的准备
  9. tigervnc远程控制linux,CentOS 6.8 安装TigerVNC 实现 Linux 远程桌面
  10. docker运行yyets_使用Docker镜像
  11. 关于微信开发与微信支付更新
  12. HDU-5441-离线化并查集
  13. 浏览器-09 javascript引擎和Chromium网络栈
  14. 计算机二级java和c哪个难,计算机二级最好考哪个 考试难度怎么样
  15. dsp正弦信号发生c语言,正弦信号发生器的DSP实现方法及比较
  16. 企业邮箱怎么弄企业邮箱是什么邮箱求一个企业邮箱账号
  17. 深度学习之神经网络基础(1)——感知器,S型神经元,梯度下降法,神经网络架构
  18. android怎么添加地铁卡,安卓手机公交卡怎么刷
  19. js移动端rem.js自适应布局代码
  20. java面向对象:三大特性:封装,继承,多态

热门文章

  1. 新项目实操分析,用付费视频进行流量变现
  2. Oracle中日期函数的使用
  3. 前端-JS基础之运算符
  4. MATLAB 中的左除(\)和 右除(/)
  5. 了解一下,Android 10 Build系统
  6. Pycharm 报错 Environment location directory is not empty的解决方法
  7. matlab获得模型切面,基于MATLAB的STL模型切片分层算法
  8. MySQL之SQL语句练习
  9. NX二次开发CreateDialog函数在UI.hxx文件和WinUser.h中的冲突
  10. mysql版本升级手册