安卓源码分析--安卓系统启动过程(一)--启动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方法主要干了:
- property_init()方法初始化属性服务。
- start_property_service();启动属性服务。
- 调用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;
1092 if (startVm(&mJavaVM, &env, zygote) != 0) {
1093 return;
1094 }
1095 onVmCreated(env);
1096
1097
1100 if (startReg(env) < 0) {
1101 ALOGE("Unable to register all android natives\n");
1102 return;
1103 }
1104
1105
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);
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
1132 char* slashClassName = toSlashClassName(className != NULL ? className : "");
1133 jclass startClass = env->FindClass(slashClassName);
1134 if (startClass == NULL) {
1135 ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
1136
1137 } else {
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
1143 } else {
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
|