🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
### 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就启动了。 如有问题请留言,转载请注明出处。