一、流程总览
系统启动->BootLoader->Linux内核->init -> zygote -> systemserver->Launcher
① 启动电源以及系统启动
当电源按下时引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序Bootloader到RAM,然后执行。
② 引导程序BootLoader
引导程序BootLoader是在Android操作系统开始运行前的一个小程序,它的主要作用是把系统OS拉起来并运行。
③ Linux内核启动
内核启动时,设置缓存、被保护存储器、计划列表、加载驱动。当内核完成系统设置,它首先在系统文件中寻找init.rc文件,并启动init进程。
④ init进程启动
解析init.rc配置文件,初始化和启动属性服务,并且启动Zygote进程。
⑤ Zygote进程启动
创建JavaVM并为JavaVM注册JNI,创建服务端Socket,启动SystemServer进程。
⑥ SystemServer进程启动
启动Binder线程池和SystemServiceManager,并且启动各种系统服务。
⑦ Launcher启动
被SystemServer进程启动的ActivityManagerService会启动Launcher,Launcher启动后会将已安装应用的快捷图标显示到界面上。
二、模块解析
Init进程
init是一个进程,确切地说,它是Linux系统中用户空间的第一个进程。由于Android是基于Linux内核的,所以init也是Android系统中用户空间的第一个进程,它的进程号是1。作为天字第一号的进程,init被赋予了很多极其重要的工作职责,简单概括为:
1、创建和挂载启动所需的文件目录。
2、初始化和启动Linux属性服务。
3、解析init.rc配置文件,首先开启ServiceManager和MediaServer等关键进程。
4、init进程fork启动Zygote服务进程。
将init的工作流程精简为以下四点:
1、解析两个配置文件,其中,将分析对init.rc文件的解析。
2、执行各个阶段的动作,创建Zygote的工作就是在其中的某个阶段完成的。
3、调用property_init初始化属性相关的资源,并且通过property_start_service启动属性服务。
4、init进入一个无限循环,并且等待一些事情的发生。重点关注init如何处理来自socket和来自属性服务器相关的事情。
init进程的入口函数是main(system/core/init/init.c)
[–>init.c]
main(){
//解析init.rc配置文件
parse_config_file("/init.rc");
//初始化和属性相关的资源
property_init();
}
[–>init.rc]
import /init.${ro.zygote}.rc
init.zygote64.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
Zygote进程
Zygote的中文翻译为“受精卵”,是生命的开始,从字面意思,我们大致可以领会到它在Android系统中的地位。Dalvik/ART,应用程序进程以及运行系统的关键服务SystemServer都是由Zygote进程创建的,所以一般也称它为孵化器。Zygote需要做很多工作,归纳起来大致有如下几条:
(1)创建Dalvik/ART(启动VM虚拟机)
startVm property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m"); 设置虚拟机heapsize,默认为16MB。绝大多数厂商都会修改这个值,一般是32MB。 heapsize不能设置过小,否则在操作大尺寸的图片时无法分配所需内存。 这里有一个问题,即heapsize既然是系统级的属性,那么能否根据不同应用程序的需求来进行动 态调整?我开始也考虑过能否实现这一构想,不过希望很快就破灭了。对这一问题,我们将在拓展部分深入讨论。
(2)从Native层进入到Java框架层。也就是说Zygote开创了Java框架层,这一步是通过Native层通过JNI方式调用ZygoteInit类的main方法来实现。Zygote的路径为:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
(3)ZygoteInit的main方法中会创建一个Service端的Socket,名称为“zygote”,用于等待AMS请求Zygote创建新的应用程序进程。
(4)ZygoteInit的main方法中还会通过fork方式创建并启动SystemServer进程
总结下关键的几个步骤:
1、启动VM虚拟机。
2、创建Zygote的Socket服务端。
3、加载预加载的类到内存。
4、加载Android通用的资源比如color、drawable等。
5、加载JNI注册、lib库等等资源。
6、fork出SystemServer进程。
7、开启循环监听客户端的请求。
Zygote是由init进程根据init.rc文件中的配置项而创建的。zygote最初的名字叫“app_process”,这个名字是在Android.mk文件中被指定的,但app_process在运行过程中,通过Linux下的pctrl系统调用将自己的名字换成了“zygote”,所以我们通过ps命令看到的进程名是“zygote”。
它的原型app_process所对应的源文件是App_main.cpp,代码如下所示
[–>App_main.cpp]
static const char ZYGOTE_NICE_NAME[] = "zygote";
int main(int argc, char* const argv[]){
set_process_name(niceName.string());//设置本进程名为zygote,这正是前文所讲的“换名把戏”。
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args);
}
}
Zygote的这个main函数虽很简单,但其重要功能却是由AppRuntime的start来完成的。下面,我们就来具体分析这个AppRuntime。
[–>AndroidRuntime.cpp]
void AndroidRuntime::start(const char*className, const bool startSystemServer)
{
//className的值是"com.android.internal.os.ZygoteInit"
//startSystemServer的值是true
//① 创建虚拟机
if(startVm(&mJavaVM, &env) != 0)
goto bail;
/*
startVm
property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");
设置虚拟机heapsize,默认为16MB。绝大多数厂商都会修改这个值,一般是32MB。
heapsize不能设置过小,否则在操作大尺寸的图片时无法分配所需内存。
这里有一个问题,即heapsize既然是系统级的属性,那么能否根据不同应用程序的需求来进行动
态调整?我开始也考虑过能否实现这一构想,不过希望很快就破灭了。对这一问题,我们将在拓展
部分深入讨论。
*/
//②注册JNI函数
if(startReg(env) < 0) {
goto bail;
}
//找到ZygoteInit类的static main函数的jMethodId。
startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");
......
/*
③通过JNI调用Java函数,注意调用的函数是main,所属的类是
com.android.internal.os.ZygoteInit,传递的参数是
“com.android.internal.os.ZygoteInit true”,
调用ZygoteInit的main函数后,Zygote便进入了Java世界!
也就是说,Zygote是开创Android系统中Java世界的盘古。
*/
}
Welcome to Java World
[–>ZygoteInit.java]
public static void main(String argv[]) {
try {
SamplingProfilerIntegration.start();
//①注册Zygote用的socket
registerZygoteSocket();
//②预加载类和资源
preloadClasses();
preloadResources();
......
//强制一次垃圾收集
gc();
//我们传入的参数满足if分支
if (argv[1].equals("true")) {
startSystemServer();//③启动system_server进程
}
}
}
SystemServer进程
ZygoteInit.java
startSystemServer();
init1
init2 启动一个ServerThread
SystemServer.java
ServerThread的run函数
//系统各种重要服务都在这里启动
startBootstrapServices();
startCoreServices(); //AMS LightsService BatteryService UsageStatsService ...
startOtherServices();
三、App 启动过程
这里以启动微信为例子说明
- Launcher 通知 AMS 要启动微信了,并且告诉AMS要启动的是哪个页面也就是首页是哪个页面。
- AMS 收到消息告诉 Launcher 知道了,并且把要启动的页面记下来。
- Launcher 进入Paused状态,告诉 AMS,你去找微信吧。
上述就是 Launche r和 AMS 的交互过程
- AMS 检查微信是否已经启动了也就是是否在后台运行,如果是在后台运行就直接启动,如果不是,AMS
会在新的进程中创建一个ActivityThread 对象,并启动其中的 main 函数。 - 微信启动后告诉 AMS,启动好了。
- AMS 通过之前的记录找出微信的首页,告诉微信应该启动哪个页面。
- 微信按照AMS通知的页面去启动就启动成功了。
四、Activity启动过程
Activity 启动过程是由 ActivityMangerService(AMS) 来启动的,底层 原理是 Binder实现的 最终交给 ActivityThread 的 performActivity 方法来启动它
ActivityThread 大概可以分为以下五个步骤
- 通过 ActivityClientRecoed 对象获取 Activity 的组件信息
- 通过 Instrument 的 newActivity 使用类加载器创建 Activity 对象
- 检验 Application 是否存在,不存在的话,创建一个,保证 只有一个 Application
- 通过 ContextImpl 和 Activity 的 attach 方法来完成一些初始化操作
- 调用 onCreate方法。