Android深入浅出之Zygote

一 目的

zygote,是Android搞出来的一个东西。网上讲这个的也非常多。第一次看到这个名字我就挺郁闷,想干嘛这是?Linux下名字都取得挺通俗易懂,深得人心。zygote?不就想模仿Linux下的fork吗?个人觉得Google取名字挺怪,包括Google本身。

不管怎样,Zygote依然是Android系统的核心,zygote是受精卵的意思,可以认为是Android framework大家族的祖先!我们本节的目的是描述下zygote的来龙去脉,顺便揭露下它的短处,以后大家可以对症下药,变异一个更加优良的品种。

二 Zygote

zygote本身是一个应用层的程序,和驱动,内核模块之类的没点关系。这下大家放心点了吧?zygote的启动由linux的祖先init启动。这个在init分析中提过。这里就不说了。

zygote,ps中看到的进程名叫zygote,其最初的名字是app_process,通过直接调用pctrl把名字给改成了”zygote”。不过不影响我们分析。

zygote的代码在framework/base/cmds/app_process/App_main.cpp中。我们一步步来看。

既然是应用程序,直接看main咯。

[---->main]

int main(int argc, const char* const argv[])

{

//参数很重要啊,还记得init分析吗?

//恩,这几个参数就是:(一定要记住我们的情景分析方法!)

//zygote /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;

//AppRuntime是个什么玩意儿?addVmArguments?好像和虚拟机有点关系喔

int i = runtime.addVmArguments(argc, argv);

[--->AppRuntime]

class AppRuntime : public AndroidRuntime

从AndroidRuntime中派生而来,是和dalvik交互的一个方便类,这里先不说了。

[---->main]

...

int i = runtime.addVmArguments(argc, argv);

....

if (i < argc) {

arg = argv[i++];

if (0 == strcmp("--zygote", arg)) {

bool startSystemServer = (i < argc) ?

strcmp(argv[i], "--start-system-server") == 0 : false;

//废话,根据我们的参数,startSystemServer=true

setArgv0(argv0, "zygote");

//改名字,不知道windows下的怎么改、linux下的可以用pctrl系统调用

set_process_name("zygote");

//start?记住我们的参数

runtime.start("com.android.internal.os.ZygoteInit",

startSystemServer);

}

} else {

return 10;

}

FT,app_main还是很简单的,但是runtime.start看起来不简单啊,传进去的那个参数

“com.android.internal.os.ZygoteInit“挺像java类的命名规则。

2.1 AppRuntime

好了,代码进入到runtime.start("com.android.internal.os.ZygoteInit",true)了。source insight直接进去看看。代码在framework/base/core/jni/AppRuntime.cpp中。

[--->void AndroidRuntime::start()]

void AndroidRuntime::start(const char* className, const bool startSystemServer)

{

LOGD("\n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<\n");

char* slashClassName = NULL;

char* cp;

JNIEnv* env;

//linux下signal的处理,没什么好说的

blockSigpipe();

//设置环境变量ANDROID_ROOT为/system

const char* rootDir = getenv("ANDROID_ROOT");

if (rootDir == NULL) {

rootDir = "/system";

setenv("ANDROID_ROOT", rootDir, 1);

}

/*启动虚拟机*/

if (startVm(&mJavaVM, &env) != 0)

goto bail;

启动虚拟机,和JAVA有关系了吧?Android最重要的sdk都是java,那虚拟机这部分肯定要进去看看的。

[--->int AndroidRuntime::startVm()]

int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)

{

//唉,大部分都是设置java虚拟机的启动参数。不过有几个参数比较重要。

//checkjni,可能没使用过jni的一辈子都不能体会

//说白了,就是我们在C++层调用jni函数的时候,会对参数或者什么的进行检查

//要是不合法的话,直接把虚拟机exit!第一个影响速度,第二个是影响程序。

//这个只作为开发时候使用。

property_get("dalvik.vm.checkjni", propBuf, "");

if (strcmp(propBuf, "true") == 0) {

checkJni = true;

} else if (strcmp(propBuf, "false") != 0) {

/* property is neither true nor false; fall back on kernel parameter */

property_get("ro.kernel.android.checkjni", propBuf, "");

if (propBuf[0] == ‘1‘) {

checkJni = true;

}

}

//设置虚拟机最大heapsize,才给16M,似乎有点少,尤其是在做图片操作的

//随便一个几百兆的图片就会把虚拟机搞死。

strcpy(heapsizeOptsBuf, "-Xmx");

property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");

opt.optionString = heapsizeOptsBuf;

mOptions.add(opt);

LOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF");

if (checkJni) {

/* extended JNI checking */

opt.optionString = "-Xcheck:jni";

mOptions.add(opt);

/* set a cap on JNI global references */

opt.optionString = "-Xjnigreflimit:2000";

mOptions.add(opt);

}

//具体dalvik虚拟机有哪些参数,可以参考Dalvik的说明

//反正调用了下面这个函数,虚拟机就按您指定的参数启动了。

if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {

LOGE("JNI_CreateJavaVM failed\n");

goto bail;

}

result = 0;

bail:

free(stackTraceFile);

return result;

}

OK,虚拟机起来了,看看我们在runtime.start中还要做什么

[--->void AndroidRuntime::start()]

if (startVm(&mJavaVM, &env) != 0)

...

//startReg?

if (startReg(env) < 0) {

goto bail;

}

看看去。

[--->int AndroidRuntime::startReg()]

为何不把startReg改成startRegister()。

int AndroidRuntime::startReg(JNIEnv* env)

{

//这个名字还是很清楚的,设置创建线程的函数为javaCreateThreadEtc

androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);

//JNI知识,自己去查JDK

env->PushLocalFrame(200);

//

if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {

env->PopLocalFrame(NULL);

return -1;

}

env->PopLocalFrame(NULL);

//搞笑,下面的注释为何不干掉?

//createJavaThread("fubar", quickTest, (void*) "hello");

return 0;

}

[---->static int register_jni_procs()]

static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)

{

for (size_t i = 0; i < count; i++) {

if (array[i].mProc(env) < 0) {//啥都没干,由传进来的参数控制..浪费我时间。

return -1;

}

}

return 0;

}

回到之前的调用,

register_jni_procs(gRegJNI, NELEM(gRegJNI), env),它的参数gRegJNI是下面这个结构

static const RegJNIRec gRegJNI[] = {

REG_JNI(register_android_debug_JNITest),

REG_JNI(register_com_android_internal_os_RuntimeInit),

REG_JNI(register_android_os_SystemClock),

REG_JNI(register_android_util_EventLog),

REG_JNI(register_android_util_Log),

...后面还有很多,好像是一些函数

};

随便挑一个跟进去看看。

[--->int register_android_debug_JNITest]

int register_android_debug_JNITest(JNIEnv* env)

{

return jniRegisterNativeMethods(env, "android/debug/JNITest",

gMethods, NELEM(gMethods));

}

其实就是注册一些JAVA中native函数在C++层对应的实行函数。

所以说:

如果你可以在这个地方加上你定制的东西。

好了,startReg完了,回到runtime.start。

[---->void AndroidRuntime::start]

if (startReg(env) < 0) {

goto bail;

}

jclass stringClass;

jobjectArray strArray;

jstring classNameStr;

jstring startSystemServerStr;

//下面这些话,都是把c++的字符串转成JAVA的字符串

//

stringClass = env->FindClass("java/lang/String");

//构造一个String数组,元素个数为2

strArray = env->NewObjectArray(2, stringClass, NULL);

classNameStr = env->NewStringUTF(className);

env->SetObjectArrayElement(strArray, 0, classNameStr);

startSystemServerStr = env->NewStringUTF(startSystemServer ? "true" : "false");

env->SetObjectArrayElement(strArray, 1, startSystemServerStr);

//java应用程序不也有main函数吗?上面的就是把C++传进来的参数,变成java的参数

[

“com.android.internal.os.ZygoteInit”,

“true”

]

jclass startClass;

jmethodID startMeth;

//

startClass = env->FindClass(slashClassName);

// 下面这个JNI调用,就真正进入java层了

startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");

//下面调用的就是com.android.internal.os.ZygoteInit类的main函数

//最后一个参数是true

env->CallStaticVoidMethod(startClass, startMeth, strArray);

bail:

free(slashClassName);

}

谢谢大家对《深入理解android 卷I/卷II》的支持。

时间: 2024-10-10 15:30:18

Android深入浅出之Zygote的相关文章

【转】推荐--《Android深入浅出》----不错

原文网址:http://www.cnblogs.com/plokmju/p/Android_Book.html 承香墨影 推荐--<Android深入浅出> 基本信息 书名:Android深入浅出 作者:张旸 著 页数: 661 出版社: 机械工业出版社; 第1版 (2014年4月17日) 语种: 简体中文 ASIN: B00JR3P8X0 品牌: 北京华章图文信息有限公司 推荐理由 以前一直在博客园发表Android相关的技术博客,经过一年多的精心准备,<Android深入浅出>

Android深入浅出之Binder机制(转)

Android深入浅出之Binder机制 一 说明 Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Binder机制来和客户端通讯交互的.所以搞明白Binder的话,在很大程度上就能理解程序运行的流程. 我们这里将以MediaService的例子来分析Binder的使用: l         ServiceManager,这是Android OS的整个服务的管理程序 l         MediaService,这个程序里边注册了提供媒体播放的服

android启动之zygote启动

上一博文介绍了init进程启动,在解析init.rc 的时候会把zygote加到service列表中,并最终启动,zygote启动的实际是app_process程序.zygote是init进程的子进程.在Android系统中,所有的应用程序以及系统服务,包括SystemServer都是由Zygote fork出来的,这就是为什么它叫zygote(受精卵)的原因.我们再来看一下.rc文件的描述: service zygote /system/bin/app_process -Xzygote /sy

Android深入浅出之 AudioTrack分析

Android深入浅出之Audio 第一部分 AudioTrack分析 一 目的 本文的目的是通过从Audio系统来分析Android的代码,包括Android自定义的那套机制和一些常见类的使用,比如Thread,MemoryBase等. 分析的流程是: l         先从API层对应的某个类开始,用户层先要有一个简单的使用流程. l         根据这个流程,一步步进入到JNI,服务层.在此过程中,碰到不熟悉或者第一次见到的类或者方法,都会解释.也就是深度优先的方法. 1.1 分析工

Android深入浅出之Binder机制【转】

Android深入浅出之Binder机制 一 说明 Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Binder机制来和客户端通讯交互的.所以搞明白Binder的话,在很大程度上就能理解程序运行的流程. 我们这里将以MediaService的例子来分析Binder的使用: <!--[if !supportLists]-->l         <!--[endif]-->ServiceManager,这是Android OS的整个服务

尝试用android studio调试zygote进程

一般都是调试system_process进程,同时也是as显示的唯一系统进程,而我就是想调试下zygote进程,结果折腾好久(用as源码调试).我这里是修改源码在zygote fork进程的时候主动等待调试器.系统版本4.4.4,修改的文件是: /home/haidragon/Desktop/android/libcore/dalvik/src/main/java/dalvik/system/Zygote.java ...................................... p

[Android] 深入浅出Android App耗电量统计

reference to : http://www.cnblogs.com/hyddd/p/4402621.html 前言 在Android统计App耗电量比较麻烦,直至Android 4.4,它仍没公开“电量统计”API或文档……额,是的,仅没有公开,并不是没有.平时在手机“设置- 电量”看到的数据 就是系统调用内部API的统计结果. 基础概念 1. 手机由众多“部件”组成,所谓“部件”是指:CPU,WIFI,GPS....所以,Android App消耗总电量为 App运行过程中,涉及各部件

Android深入浅出自定义控件(二)

在我的上篇博文Android深入迁出自定义控件(一)中介绍了如何自定义View控件,本篇博文主要介绍如何自定义ViewGroup 什么是ViewGroup? 在Android的树状结构图中,ViewGroup类衍生出我们所熟悉的LinearLayout.RelativeLayout等布局: 简单来说,ViewGroup其实就相当于所有布局的父亲,所以我们可以通过自定义ViewGroup类实现千变万化的布局. 自定义ViewGroup主要分为以下几个步骤: 1.创建自定义ViewGroup类,继承

Android深入浅出之Binder机制

一说明 Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Binder机制来和客户端通讯交互的.所以搞明白Binder的话,在很大程度上就能理解程序运行的流程.我们这里将以MediaService的例子来分析Binder的使用:l        ServiceManager,这是Android OS的整个服务的管理程序l        MediaService,这个程序里边注册了提供媒体播放的服务程序MediaPlayerService,我们最后只