5

Android Framework是怎么启动的?

 3 years ago
source link: http://www.androidchina.net/4191.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Framework运行环境是怎样的?

安卓系统启动过程其实是建立一套系统运行需要的环境。
Framework运行环境如下:

这里写图片描述

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

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

  • Socket服务端。用于接收启动新的Dalvik进程的命令。
  • 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会孵化出新的进程。

这样的架构有两个特点:

  • 每一个进程都是一个Dalvik虚拟机,Dalvik虚拟机是一种类似于java虚拟机的程序。
  • 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不同,新进程将拥有和原始进程完全相同的进程信息。进程的信息包括该进程所打开的文件描述符列表、所分配的内存等。当新进程被创建后,两个进程将共享已经分配的内存空间,如果其中一个需要向内存中写入数据时,操作系统才复制一份目标地址空间,并将要写的数据写入到新的地址中。这种“仅当写的时候才复制”的机制可以最大限度的在多个进程中共享物理内存。

举个栗子:

去乌镇见一下习大大和去乌镇吃一次丁磊的猪肉,这是两个进程,但是两个进程中的很多任务是相同的,先订机票,做地铁到机场,做几小时飞机过去。到了之后不同的就是见习大大和吃猪肉。如果可以先雇一个秘书进程让它订机票、做地铁、做飞机,到乌镇。然后秘书在复制出两个秘书,一个去见习大大,一个去吃猪肉,好处是节省了大量内存。

Zygote进程就是本例中的“秘书进程”,那些“订机票、做地铁、乘飞机”就是Zygote进程中加载的preload-classes类的功能。

这样新的进程就脱离的Zygote进程的孵化成为一个真正的应用进程。

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就启动了。

转载请注明:Android开发中文站 » Android Framework是怎么启动的?


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK