### Framework运行环境是怎样的?
安卓系统启动过程其实是建立一套系统运行需要的环境。
Framework运行环境如下:
![这里写图片描述](https://box.kancloud.cn/2016-03-28_56f8ee3a606e8.jpg "")
安卓系统中运行的第一个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就启动了。
如有问题请留言,转载请注明出处。