Android Framework的启动方法及原理详解

安卓系统中运行的第一个Dalvik虚拟机叫做zygote,意思是“卵”。这“卵”还是挺有用的,因为接下来所有的Dalvik虚拟机进程都是这个“卵”孵化出来的。

zygote进程中包含两个主要模块,分别如下:

1、Socket服务端。用于接收启动新的Dalvik进程的命令。

2、Framework共享类及共享资源。当zygote进程启动后会加载一些共享的类及资源,其中共享类是在preload-classes文件中被定义的,共享资源是在preload-resources中被定义的。其他Dalvik进程是被zygote进程孵化出来的,所以这些类和资源加载后,新的Dalvik进程就可以直接使用这些类和资源就达到了共享目的。

zygote进程对应的程序是app_process,该程序在system/bin目录下。

zygote孵化出的第一个Dalvik进程是SystemServer,该进程对应的程序依然是app_process,因为该进程是从app_process中孵化出来的。

SystemServer中创建了一个Socket客户端,之后所有的Dalvik进程都将通过该Socket客户端间接被启动,Ams负责管理这个客户端。如果需要启动新的APK进程时,Ams会通过该Socket客户端向zygote进程的Socket服务端发送一个启动命令,然后zygote会孵化出新的进程。

这样的架构有两个特点:

1、每一个进程都是一个Dalvik虚拟机,Dalvik虚拟机是一种类似于java虚拟机的程序。

2、zygote进程会预先装载共享类和共享资源,这些类和资源其实就是SDK中定义的大部分类和资源。当通过zygote孵化出新进程后,新的APK只需要去加载APK自身包含的类和资源,这样多个APK就可以共享Framework资源了。

和Dalvik虚拟机有联系的可执行程序有哪些?

1.dalvikvm

java程序运行时都是由一个虚拟机来解释java字节码,将这些字节码翻译成本地CPU指令码然后执行。dalvikvm的作用就是创建一个虚拟机并执行参数中指定的java类。

2.dvz

dvz的作用是从zygote进程中孵化出一个新的进程,新进程其实就是一个Dalvik虚拟机。该进程与dalvikvm启动的虚拟机相比,区别是该进程中已经预装了Framework的大部分类和资源。

3.app_process

Framework在启动时需要加载运行两个特定java类,一个是ZygoteInit.java,一个是SystemServer.java。为了方便使用,系统才提供了一个app_process进程,该进程会自动运行这两个类,app_process其实就是使用dalvikvm启动ZygoteInit.java,启动后会加载Framework中得大部分类和资源。

Zygote是如何启动的?

  1. 在init.rc中配置Zygote启动参数
  2. 启动Socket服务端口,当Zygote服务从app_process开始启动后,会启动一个Dalvik虚拟机,虚拟机第一个执行的java类就是ZygoteInit.java,该类第一个重要的工作就是启动一个Socket服务端口,该Socket端口用于接收启动新进程的命令。
  3. 加载preload-classes,在Zygote类的main()函数中,创建完Socket服务端后还不能立即孵化出新的进程,因为这个“卵”还没有必须的“核酸”,这个“核酸”就是指预装的Framework大部分类及资源。
  4. 加载preload-resources,preload-resources包含两类资源,一类是drawable资源,一类是color资源。加载这些资源是在preloadResource()函数中完成的,该函数调用preloadDrawable()和preloadColorStateLists()加载这两类资源,原理就是把这些资源读出来放到一个全局变量中,只要该类对象不被销毁,这些全局变量就会一直保存。
  5. 使用fork启动新的进程,fork是Linux系统的一个系统调用,作用就是复制当前进程产生一个新的进程。除了进程id不同,新进程将拥有和原始进程完全相同的进程信息。进程的信息包括该进程所打开的文件描述符列表、所分配的内存等。当新进程被创建后,两个进程将共享已经分配的内存空间,如果其中一个需要向内存中写入数据时,操作系统才复制一份目标地址空间,并将要写的数据写入到新的地址中。这种“仅当写的时候才复制”的机制可以最大限度的在多个进程中共享物理内存。

SystemServer 进程是如何启动的?

SystemServer进程是Zygote孵化出的第一个进程,然后再配置SystemServer进程的环境。

1.启动各种系统服务线程

SystemServer进程在Android运行环境中扮演了“神经中枢”的作用,APK应用中能够直接交互的大部分系统服务都在该进程中运行,常见的有WindowManagerServer(Wms)ActivityManagerService(Ams)、PackageManagerServer(Pms),这些系统服务都是以一个线程的方式存在于SystemServer进程中。

2.启动第一个Activity

当以上服务线程都启动后,其中Ams服务是systemReady()调用完成最后启动的,在Ams的systemReady()函数的最后一段代码则发出了启动任务队列中最上面一个Activity消息。

在Ams的startHomeActivityLocked()中,系统发出了一个category字段包含CATEGORY_HOME的intent,代码如下:

intent.setComponent(mTopComponent);
if(mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL){
    intent.addCategory(Intent.CATEGORY_HOME);
}

只要应用声明自己能够响应该Intent,那么就可以被认为是Home程序。当系统中有多个程序能够响应该Intent时,系统会弹出一个对话框,让用户选择启动哪个程序,也允许用户记住该选择。

到此第一个Activity就启动了。

    原文作者:feyshine
    原文地址: https://blog.csdn.net/fei_xiang_feng/article/details/51610961
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞