Framework启动流程

来源:互联网 发布:零售业大数据案例 编辑:程序博客网 时间:2024/05/16 21:19
  • Framework运行环境

  1. 第一个Dalvik虚拟机叫做zygote,其他进程都是由他启动的。

  2. zygote进程包括两个模块,Socket服务端,Framework共享类及共享资源。

  3. zygote进程对应程序是app_process,第一个孵化出进程为SystemServer,对应程序也是app_process

  • zygote的启动

  1. 启动命令存储在init.rc中.

  2. service zygote /system/bin/app_proscess -Xzygote /system/bin --zygote --start-system-server

    socket zygote stream 666

    onrestart write /sys/android_power/request_state wake

    onrestart write /sys/power/state on

    onrestart restart media

    onrestart restart netd


    service zygote /system/bin/app_proscess 将zygote加入系统服务中 后加入可执行路径。

    -Xzygote 虚拟机启动时所用参数

    /system/bin 虚拟机程序所在位置

    --zygote 以ZygoteInit类作为虚拟机执行的入口

    --start-system-server 在使用--zygote之后才生效,告知启动完毕后,第一个孵化出SystemServer

    socket zygote stream 666 指定该服务所使用到的socket,后面参数依次是名称,类型,端口地址

    onrestart 指定该服务重启条件,满足这些条件后,zygote重启

    启动命令存储在init.rc中

  3. onrestart 指定该服务重启条件,满足这些条件后,zygote重启

  4. 启动soceket服务端口

    在ZygoteInit类的main()函数中 启动Socket服务端口,用于接受启动新进程的命令。在静态函数registerZygoteSocket()中完成的

  5. 加载preload-classes

    preload-classes文件通过WritePreloadedClassFile.java类生成。在编译过程中,将preload-classes打包到framework.jar中。在ZygoteInit中调用preloadClasses()完成类装载。

  6. 加载preload-resources

    preloadResources()完成资源加载。reloadDrawables()和preloadColorStateLists()

  7. 使用fork启动新进程

    fork函数返回值如果大于0 代表父进程,等于0代表子进程。

    ZygoteInit的runSelectLoopMode()函数中调用Zygte.Connection类的runOnce()完成复制进程。

    forkAndSpecialize()功能同fork,增加了进一步的封装和处理。

    创建完进程后,需要关闭socket服务端,并且调用新进程重指定的class文件的main作为新进程的入口。这些操作根据forkAndSpecialize返回的pid值,在handleChildProc()中完成。

  8. folk是Linux系统的一个系统调用,其作用是复制当前进程,产生一个新的进程。新进程将拥有和原始进程完全相同的进程信息,除了进程id不同。进程信息包括该进程所打开的文件描述符列表、所分配的内存等。当新进程被创建后,两个进程将共享已经分配的内存空间,直到其中一个需要向内存中写入数据时,操作系统才负责复制一份目标地址空间,并将要写的数据写入到新的地址中,这就是所谓的copy-on-write机制,即"仅当写的时候才复制",这种机制可以最大限度地在多个进程中共享物理内存。

           第一次接触folk的读者可能觉得奇怪,为什么要复制进程呢?在大家熟悉的Windows操作系统中,一个应用程序一般对应一个进程,如果说要复制进程,可能的结果就是从计算器程序复制出一个Office程序,这听起来似乎很不合理。要立即复制进程就需要首先了解进程的启动过程。

           在所有的操作系统中,都存在一个程序装载器,程序装载器一般会作为操作系统的一部分,并由所谓的Shell程序调用。当内核启动后,Shell程序会首先启动。常见的Shell程序包含两大类,一类是命令行界面,另一类是窗口界面,Windows系统中Shell程序就是桌面程序,Ubuntu系统中的Shell程序就是GNOME桌面程序。Shell程序启动后,用户可以双击桌面图标启动指定的应用程序,而在操作系统内部,启动新的进程包含三个过程。

    第一个过程,内核创建一个进程数据结构,用于表示将要启动的进程。

    第二个过程,内核调用程序装载器函数,从指定的程序文件读取程序代码,并将这些程序代码装载到预先设定的内存地址。

    第三个过程,装载完毕后,内核将程序指针指向到目标程序地址的入口处开始执行指定的进程。当然,实际的过程会考虑更多的细节,不过大致思路就是这么简单。


  • SystemServer进程的启动

  1. zygote类使用startSystemServer()启动,而不是使用forkAndSpecialize()

  2. Wms,Ams,Pms都是在SystemServer进程中的线程

  3. init1()进行一些与Dalvik虚拟机相关的初始化。init2()完成主要的系统服务,在init2()创建ServerThread对象,直接运行该进程。线程run()内部开始真正启动各种服务线程。

  • 启动第一个Activity

  1. AmS服务是systemReady()调用完成最后启动

  2. mMainStack中第一个Activity对象就是第一个调用的activity

  3. AmS的startHomeActivityLocked(),系统发出包含ATEGORY_HOME的intent,只要能相应intent,就可被认得为home程序,有多个的时候提供选择。

1 0
原创粉丝点击