安卓源码分析--安卓系统启动过程(一)--启动zygote

ps:本文章基于刘望舒大佬著作《android进阶解密》所写进行增加个人理解,细节。并简化具体调用流程。主要方便自己,方便大家随时翻阅。部分是个人理解,如果有错请大佬联系更改。

第一步:按下电源

ROM:只读存储器( Read-OnlyMemory,ROM)只能读出无法写入信息。信息一旦写入后就固定下来,即使切断电源,信息也不会丢失,所以又称为固定存储器。ROM所存数据通常是装入整机前写入的,整机工作过程中只能读出,ROM所存数据稳定断电后所存数据也不会改变,并且结构较简单,使用方便,因而常用于存储各种固定程序和数据

当电源按下,从ROM在装入整机前写入的程序开始执行。加载引导程序BootLoader到内存中,执行。

第二步:引导程序BootLoader

在嵌入式操作系统中,BootLoader是在操作系统内核运行之前运行。可以初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境。在嵌入式系统中,通常并没有像BIOS那样的固件程序(注,有的嵌入式CPU也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由BootLoader来完成。在一个基于ARM7TDMI core的嵌入式系统中,系统在上电或复位时通常都从地址0x00000000处开始执行,而在这个地址处安排的通常就是系统的BootLoader程序

BootLoader是安卓OS运行起来之前的一个小程序,他的主要作用是把系统OS拉起运行。

第三步:Linux内核启动

内核启动,设置缓存,被保护存储器,计划列表,加载驱动。在内核完成系统初始化后,在系统文件寻找init.rc文件,并启动init进程。

第四步:init进程启动

之前所说Linux内核启动后会在系统文件寻找init.rc文件,并启动init进程,init进程的入口函数位于/system/core/init/init.cpp的main函数。
init进程main方法主要干了:

  1. property_init()方法初始化属性服务。
  2. start_property_service();启动属性服务。
  3. 调用LoadBootScripts()函数,函数内部调用parser.ParseConfig("/init.rc");解析init.rc配置文件。

第五步:Zygote进程启动

在Android系统中,zygote是一个native进程,是Android系统上所有应用进程的父进程,我们系统上app的进程都是由这个zygote的fork函数出来的。

init进程解析init.rc文件,init.rc配置文件下有以下代码:

init.rc由安卓初始化语言编写
/system/core/rootdir/init.rc
on nonencrypted //设置触发器
    class_start main
    class_start late_start
    ......

init.rc由安卓初始化语言编写,class_start对应/system/core/init/builtins.cpp的do_class_start函数。class_start main就是启动那些名为main的Service,Zygote的classname就是main。通过android专门处理该文件的类最终调用/system/core/init/service.cpp
的start函数。其中调用了execve函数(安卓源码未找到,最新可能有修改)进入了app_main.cpp的main函数中。/frameworks/base/cmds/app_process/app_main.cpp

init主进程启动,解析init.rc后依次exec fork启动相关的进程,其中以class main和core为首的service将会率先启动,surfaceflinger service作为service之一,启动后 开始启动动画显示,后台其他服务进程完成初始化,待Systemserver的其他核心service启动后,ActivityManagerService将会初始化完成并启动第一个lunch activity即桌面程序,在渲染图像前,需要让surfaceflinger 停止动画的显示,故由AMS通知surfaceflinger 停止显示,以方便Lunch最终display到UI上。这段显示的时间,基本就是后台服务的初始化运行,其中以SystemServer的耗时较长,导致开机动画一直循环显示。
————————————————
版权声明:本文为CSDN博主「天才2012」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/gzzaigcnforever/article/details/19995509

/frameworks/base/cmds/app_process/app_main.cpp
...
349    if (zygote) {
350        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
351    } else if (className) {
352        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
353    } else {
354        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
355        app_usage();
356        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
357    }
...

启动调用了runtime的start函数

/frameworks/base/core/jni/AndroidRuntime.cpp
1056 void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
1057{
...
1089	JniInvocation jni_invocation;
1090    jni_invocation.Init(NULL);
1091    JNIEnv* env;
		//创建java虚拟机
1092    if (startVm(&mJavaVM, &env, zygote) != 0) {
1093        return;
1094    }
1095    onVmCreated(env);
1096
1097    /*
1098     * Register android functions.
1099     */
		//注册jNI方法 
1100    if (startReg(env) < 0) {
1101        ALOGE("Unable to register all android natives\n");
1102        return;
1103    }
1104
1105    /*
1106     * We want to call main() with a String array with arguments in it.
1107     * At present we have two arguments, the class name and an option string.
1108     * Create an array to hold them.
1109     */
1110    jclass stringClass;
1111    jobjectArray strArray;
1112    jstring classNameStr;
1113
1114    stringClass = env->FindClass("java/lang/String");
1115    assert(stringClass != NULL);
1116    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
1117    assert(strArray != NULL);
		//调用传入的参数com.android.internal.os.ZygoteInit
1118    classNameStr = env->NewStringUTF(className);
1119    assert(classNameStr != NULL);
1120    env->SetObjectArrayElement(strArray, 0, classNameStr);
1121
1122    for (size_t i = 0; i < options.size(); ++i) {
1123        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
1124        assert(optionsStr != NULL);
1125        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
1126    }
1127
1128    /*
1129     * Start VM.  This thread becomes the main thread of the VM, and will
1130     * not return until the VM exits.
1131     */
		//替换com.android.internal.os.ZygoteInit中的.为/
1132    char* slashClassName = toSlashClassName(className != NULL ? className : "");
		//找到ZygoteInit类
1133    jclass startClass = env->FindClass(slashClassName);
1134    if (startClass == NULL) {
1135        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
1136        /* keep going */
1137    } else {
			//找到ZygoteInit类的main方法
1138        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
1139            "([Ljava/lang/String;)V");
1140        if (startMeth == NULL) {
1141            ALOGE("JavaVM unable to find main() in '%s'\n", className);
1142            /* keep going */
1143        } else {
				//jni调用main方法
1144            env->CallStaticVoidMethod(startClass, startMeth, strArray);
1145
1146#if 0
1147            if (env->ExceptionCheck())
1148                threadExitUncaughtException(env);
1149#endif
1150        }
1151    }
}

这样就从native层进入了zygote的java层,之前从未调用java方法。
ZygoteInit对应源码/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值