• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > 详细分析Android中实现Zygote的源码

详细分析Android中实现Zygote的源码

作者:低调小一 字体:[增加 减小] 来源:互联网 时间:2017-05-28

低调小一 通过本文主要向大家介绍了android zygote,android7.0 zygote,九星飞宫详细分析,istj型性格详细分析,awr报告详细分析等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

概述

在Android系统中,所有的应用程序进程,以及用来运行系统关键服务的System进程都是由zygote进程负责创建的。因此,我们将它称为进程孵化器。zygote进程是通过复制自身的方式来创建System进程和应用程序进程的。由于zygote进程在启动时会在内部创建一个虚拟机实例,因此,通过复制zygote进程而得到的System进程和应用程序进程可以快速地在内部获得一个虚拟机实例拷贝。
zygote进程在启动完成之后,会马上将System进程启动起来,以便它可以将系统的关键服务启动起来。下面我们将介绍zygote进程的启动脚本,然后分析它和System进程的启动过程。
zygote分析

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

</div>


在我之前的一篇博客中已经分析了init进程是如何启动service服务了,需要了解的同学可以参考这篇文章:Android init进程——解析配置文件

通过zygote服务的启动脚本,我们可以知道,zygote进程的实际是二进制文件app_process的调用,我们就从这个应用程序的main函数入手去分析一下zygote进程的启动过程,源码如下(/frameworks/base/cmds/app_process/app_main.cpp):

/**
 * 将-Xzygote加入到JavaVMOption中,返回/system/bin参数指向的下标
 */
int AndroidRuntime::addVmArguments(int argc, const char* const argv[])
{
  int i;

  for (i = 0; i < argc; i ++) {
    if (argv[i][0] != '-') {
      return i;
    }
    if (argv[i][1] == '-' && argv[i][2] == 0) {
      return i + 1;
    }

    JavaVMOption opt;
    memset(&opt, 0, sizeof(opt));
    opt.optionString = (char*)argv[i];
    mOptions.add(opt);
  }
  return i;
}

int main(int argc, char* const argv[])
{
  // zygote call parameters
  // /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

  // These are global variables in ProcessState.cpp
  mArgC = 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 tp '--' or first non '-' arg goes to the vm
  int i = runtime.addVmArguments(argc, argv);

  // 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;
  while (i < argc) {
    const char* arg = argv[i ++];
    if (!parentDir) {
      parentDir = arg;
    } 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)) {
      niceName = arg + 12;
    } else {
      className = arg;
      break;
    }
  }

  if (niceName && *niceName) {
    setArgv0(argv0, niceName);
    set_process_name(niceName);
  }

  runtime.mParentDir = parentDir;

  if (zygote) {
    // 进入到AppRuntime的start函数
    runtime.start("com.android.internal.os.ZygoteInit",
      startSystemServer? "start-system-server" : "");
  } else if (className) {
    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;
  }
}

</div>


在zygote的main函数中,通过AppRuntime runtime代码创建了一个AppRuntime对象runtime,接下来Zygote进程就是通过它来进一步启动的。
init.rc中关于启动zygote命令中包含了–zygote参数,所以在if(strcmp(arg, “–zygote”) == 0)判断的时候,会将niceName赋值为”zygote”,然后通过set_process_name(niceName)函数将当前进程的名称设置为zygote。这也是为什么调用的脚本为/system/bin/app_process,而进程名为zygote的原因。set_process_name函数的源码如下(/system/core/libcutils/process_name.c):

static const char* process_name = "unknown";
void set_process_name(const char* new_name)
{
  if (new_name == NULL) {
    return;
  }

  int len = strlen(new_name);
  char* copy = (char*)malloc(len + 1);
  strcpy(copy, new_name);
  process_name = (const char*) copy;
}

</div>

从init.rc文件中关于zygote进程的配置参数可知,Zygote进程传递给应用程序app_process的启动参数arg还包含一个”–start-system-server”选项。因此,在调用AppRuntime对象runtime的成员函数start时,第二个参数为”start-system-server”,表示zygote进程启动完成之后,需要将system进程启动起来。
AppRuntime分析

AppRuntime类的成员函数start是从父类AndroidRuntime继承下来的,因此,接下来我们就继续分析AndroidRuntime类的成员函数start的实现,函数源码位置:/frameworks/base/core/jni/AndroidRuntime.cpp:

char* AndroidRuntime::toSlashClassName(const char* className)
{
  char* result = strdup(className);
  for (char* cp = result; *cp != '\0'; cp ++) {
    if (*cp == '.') {
      *cp = '/';
    }
  }

  return result;
}

/**
 * Start the Android runtime. This involves starting the virtual machine
 * and calling the "static void main(String[] args)" method int the class
 * named by "className".
 *
 * 这两个参数的值分别为:
 * const char* className = "com.android.internal.os.ZygoteInit";
 * const char* 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) {
    const int LOG_BOOT_PROGRESS_START = 3000;
    LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
  }

  // 设置ANDROID_ROOT环境变量
  const char* rootDir = getenv("ANDROID_ROOT");
  if (rootDir == NULL) {
    rootDir = "/system";
    if (!hasDir("/system")) {
      LOG_FATAL("No root directory specified, and /android dose not exist.");
      return;
    }
    setenv("ANDROID_ROOT", rootDir, 1);
  }


  JniInvocation jni_invocation;
  jni_invocation.Init(NULL);
  JNIEnv* env;
  // 1. 创建虚拟机
  if (startVm(&mJavaVM, &env) != 0) {
    return;
  }
  onVmCreated(env);

  // 2. 注册JNI函数
  if (startReg(env) < 0) {
    ALOGE("Unable to register all android natives\n");
    return;
  }

  jclass stringClass;
  jobjectArray strArray;
  jstring classNameStr;
  jstring optionsStr;

  stringClass = env->FindClass("java/lang/String");
  assert(stringClass != NULL);
  // 创建一个有两个元素的String数组,用Java代码表示为:String[] strArray = new String[2];
  strArray = env->NewObjectArray(2, stringClass, NULL);
  assert(strArray != NULL);
  classNameStr = env->NewStringUTF(className);
  assert(classNameStr != NULL);
  // 设置第一个元素为"com.android.internal.os.ZygoteInit"
  env->SetObjectArrayElement(strArray, 0, classNameStr);
  optionsStr = env->NewStringUTF(options);
  // 设置第二个元素为"start-system-server"
  env->SetObjectArrayElement(strArray, 1, optionsStr);

  // 将



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 详细分析Android中实现Zygote的源码

相关文章

  • 2017-05-28c++连接mysql数据库的两种方法(ADO连接和mysql api连接)
  • 2017-05-28c语言中用字符串数组显示菜单的解决方法
  • 2017-05-28详解C++中的内联函数和函数重载
  • 2017-05-28总结C/C++面试中可能会碰到的字符串指针题
  • 2017-05-28C语言实现输入一个字符串后打印出该字符串中字符的所有排列
  • 2017-05-28详解Linux的SOCKET编程
  • 2017-05-28Win10中VC2013安装Unit test组件出现问题解决方案
  • 2017-05-28C++ 智能指针深入解析
  • 2017-05-28C++开发的Redis数据导入工具优化
  • 2017-05-28C语言实现找出二叉树中某个值的所有路径的方法

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 千万不要被阶乘吓倒
    • 使用C语言求解扑克牌的顺子及n个骰子的点数问题
    • 使用C语言求二叉树结点的最低公共祖先的方法
    • 关于C++中虚拟继承的一些总结分析
    • C++设计模式编程中Template Method模板方法模式的运用
    • 排序算法模板实现示例分享
    • C++中const应放在类型前还是后
    • VC读配置文件实例
    • C++中指针指向二维数组实例详解
    • VC多线程编程详解

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有