IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 安卓源码分析--安卓系统启动过程(一)--启动zygote -> 正文阅读

[嵌入式]安卓源码分析--安卓系统启动过程(一)--启动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

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

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-07-28 07:59:49  更:2021-07-28 08:01:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 10:32:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计