Android开机启动过程

Android开机图解.png
Android开机图解2

Android系统启动过程

  • BootLoader与Linux内核启动
  • init进程
  • zygote进程
  • systemServer启动

init进程

init进程是Android系统启动的第一个进程。
init进程main方法做了如下工作:

  • first stage 初始化环境变量和各种文件系统目录,klog初始化等
  • selinux相关初始化完成,然后切换second stage 重启init进程
  • 属性服务初始化,将各种系统属性默认值填充到属性Map中
  • 创建epoll描述符结合注册socket监听,处理显示启动进程和挂掉的子进程重启
  • 解析init.rc。把各种action、service等解析出来的填充到相应链表容器管理
  • 有序将early-init、init等各种cmd加入到执行队列action_queue链表中
  • 进入while()循环依次取出执行队列action_queue中的command执行,fork包括app_process在内的各种进程,epoll阻塞监听处理来自挂掉的子进程的消息,根据设定策略restart子进程。

zygote进程

Zygote初始化时会创建创建虚拟机,同时把需要的系统类库和资源文件加载到内存里面。Zygote fork出子进程后,这个子进程也继承了能正常工作的虚拟机和各类系统资源,接下来子进程只需要装载APK文件的字节码文件就可以运行了。这样应用程序的启动时间就会大大缩短。
Zygote创建应用程序时却只使用了fork,没有调用exec。Android应用中执行的是Java代码,Java代码的不同才造成了应用的区别,而对于运行Java的环境,要求却是一样的。如下图:


Zygote进程load Apk应用

Zygote进程创建AppRuntime对象。
AndroidRuntime类是安卓底层系统超级重要的一个类,它负责启动虚拟机以及Java线程。AndroidRuntime类是在一个进程中只有一个实例对象,并将其保存在全局变量gCurRuntime中。

AndroidRuntime类的start函数其实主要就是做了3件事情:
  • 创建了一个JniInvocation的实例,并且调用它的成员函数init来初始化JNI环境。
  • 调用AndroidRuntime类的成员函数startVm来创建一个虚拟机即其对应的JNI接口,即创建一个JavaVM接口和一个JNIEnv接口
  • 有了上述的JavaVM接口和JNIEnv接口之后,就可以在Zygote进程中加载指定的class了。

在AndroidRuntime中又创建了一个Runtime实例(Runtime在ART中代表Java的运行时环境。一个进程只有一个ATR虚拟机,一个ART虚拟机只有一个Runtime)。

在Runtime(Java运行时环境)准备完毕之后,Zygote会调用Java的初始化代码做如下工作:

  • 解析调用的参数,即argv[],通过for循环遍历解析,通过string的方法来判断,主要出是初始化startSystemServer、abiList和socketName变量
  • 调用registerZygoteSocket(socketName)方法注册Zygote的socket监听接口,用来启动应用程序的消息
  • 调用preload()方法装载系统资源,包括系统预加载类、Framework资源和openGL的资源。这样当程序被fork处理后,应用的进程内已经包含了这些系统资源,大大节省了应用的启动时间。
  • 调用startSystemServer()方法启动SystemServer进程。
  • 调动runSelectLooper方法进入监听和接收消息的循环。
预加载系统类和资源

预加载过程:

  • 预加载Java类
  • 预加载资源
  • 预加载OpenGL资源
  • 预加载文本资源
  • 初始化WebView
zygote启动过程总结
  • 创建AppRuntime对象,并且调用其start函数。之后zygote的核心初始化都由AppRuntime中。
  • 调用startVm创建Java虚拟机,然后调用startReg来注册JNI函数
  • 通过JNI调用com.android.internal.os.ZygoteInit的main函数,从此进入了Java世界
  • 调用registerZygoteSocket创建可以响应子孙后台请求的socket。同时zygote调用preload函数预加载常用的类、资源等,为Java世界添砖加瓦
  • 调用startSystemServer函数fork一个system_server来为Java服务
  • Zygote完成了Java的初始工作后,便调用runSelectLoop来让自己无限循环等待。之后,如果收到子孙后台的请求,它便会醒来为他们工作。

SystemServer

SystemServer是Android系统的核心之一,大部分Android提供的服务都运行在这个进程里,SystemServer中运行的服务总共有60多种。为了防止应用进程对系统造成破坏,Android的应用进程没有权限直接访问设备的底层资源,只能通过SystemService中的代理访问。通过Binder,用户进程在使用SystemService中的服务并没有太多不便变之处。

SystemServer的主要工作如下:

  • 调用createSystemContext()来创建系统上下文
  • 创建SystemServiceManager
  • 启动各种服务
初始化系统上下文——createSystemContext()方法解析
  • 获取系统Context,即getSystemContext()

    • LoadApk对象的实例化
      LoadApk对象用来保存一个apk信息,这个构造方法中会将使用的包名指定为"android"。
      而framework-res.apk的包名为"android"。因此,getSystemServer()方法返回mSystemContext对象所对应的apk文件即是framework-res.apk
    • ContextImpl对象的实例化
      我们知道首次执行getSystemContext,会创建LoadedApk和contextImpl对象,接下来利用刚创建的LoadedApk对象来创建新的ContextImpl对象。
  • 创建activityThread对象——ActivityThread.systemMain()方法研究
    ActivityThread是一个Application的主线程类,(记住,它不是Thread,因为它既没有继承Thread,也没有实现Runnable)
    由于SystemServer不是一个应用程序,但是这里为什么还要创建ActivityThread?因为SystemServer不仅仅是一个后台进程,同时它还是一个运行着组件的Service进程,很多系统的对话框就是从SystemServer中显示出来的,因此,SystemServer本身也需要一个和APK应用类似的上下文环境。

    • 创建ActivityThread实例
      1. 创建ApplicationThread对象。用于基于的BinderIPC通信
      2. 创建H对象mH,以及主线程的Looper对象mLooper
    • ActivityThread的attach(boolean)方法的解析
      1. 创建Instrumentation对象
      2. 通过调用ContextImpl.createAppContext方法来创建ContextImpl对象
      3. 通过调用context.mPackageInfo.makeApplication创建mInitialApplication对象
      4. 调用mInitialApplication对象的onCreate()
        DropBox:DropBox是Android在Froyo(API 8)中引用的用来持续化存储系统数据的机制,主要记录Android运行过程中、内核、系统进程、用户进程等出现严重问题时的log,可以认为这是一个可持续存储的系统级别的log
        Instrumentation:一个应用进程,对应一个Instrumentation,这个类的对象,会被优先创建出来,然后通过它来创建其他组件,它也是系统与其他组件交互的桥梁,因此通过它可以监听组件和系统之间的各种交互。
        LoadedApk:在讲解APK安装的时候我们说过,一个应用对应一个LoadedApk对象,里面包含了整个APK的相关信息。其中context.mPackageInfo是一个LoadedApk对象
      
      • ContextImpl.createAppContext方法的解析
        直接new了一个ContextImpl对象
      • LoadedApk.makeApplication方法的解析
        • LoadedApk的getClassLoader()方法的解析
          区分是否是系统进程,系统进程通过ClassLoader.getSystemClassLoader()来获取系统的类加载器。
        • Instrumentation的newApplication(cl, appClass, appContext)方法的解析
          通过反射来创建一个Application的实例,最后调用attach(context)来绑定一个Context。
创建SystemServiceManager

把SystemServiceManager放到LocalServicesd的sLocalServiceObjects中,其中sLocalServiceObjects是一个ArrayMap。这样后面在通过类名,就可以找到SystemServiceManager的对象了。

启动各种服务
  • startBootstrapServices();
  • startCoreServices();
  • startOtherServices();


    system_server服务的启动流程
启动Launcher

SystemServer.java的startOtherServices()方法里面调用 mActivityManagerService.systemReady()方法,里面又会调用startHomeActivityLocked(mCurrentUserId, "systemReady");最后会调用startHomeActivity(Intent,ActivityInfo,String)方法。

总结

参考文献

Android启动流程系列

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容