欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-23 16:55:10
...

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

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

/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