Android 系统启动流程

3,526 阅读7分钟

概述

站在巨人的肩膀上学习,本片博客参考 gityuan,用于笔记和巩固知识

Android 架构

在这里插入图片描述
这个是Google官方提供的经典的分层架构图,从下向上依次是,Linux内核HAL系统Native库和Android RuntimeJava框架层应用层,其中每一层都有若干的子模块和子系统

Google提供的5层很经典,但是为了更进一步的透视Android 系统架构,以进程的视角,以分层的架构,来诠释Android的全貌,诠释Android 全貌的内在联系

Android 启动架构图

在这里插入图片描述

Android 系统启动过程由上图从下向上的一个过程,由Boot Loader引导开机,然后依次进入Kernel -> Native-> Framework-> App,下面简要介绍这几个过程

开机(关于Loader层)

  • Boot ROM:当手机处于关机的状态,长按Power键开机,引导芯片从固化在ROM里预设的代码开始执行,然后加载程序到RAM
  • Boot Loader:这是启动Android系统之前的引导程序,主要是检查RAM,初始化硬件参数等工能

关于Kernel (Linux内核层)

Android 平台的基础是Linux内核,比如ART虚拟机最终调用的是Linux内核执行的功能,Linux内核的安全机制为Android提供相应的保障,也允许设备制造商为内核开发硬件驱动程序

  • 启动Kernel的swapper进程(pid=0),该进程又称为idle进程,系统初始化过程Kernel从无到有,开创的第一个进程,用于初始化进程管理,内存管理,加载Display,Camera Driver,Binder Driver,等相关工作
  • 启动kthreadd进程(pid=2),是Linux的内核进程,会创建内核工作线程kworkder,软中断线程ksoftirqd,thermal等内核守护进程,kthreadd进程是所有内核进程的鼻祖

关于硬件抽闲层(HAL)

硬件抽象层(HAL)提供标准接口,HAL包括多个库模块,每个模块都为特定的硬件组件实现一组接口,比如Wifi/蓝牙模块,当框架API请求访问硬件时,Android系统将为该硬件加载相应的库模块

Android Runtime 和 系统库

每个应用都在自己的进程中运行,都有自己的虚拟机实例,ART通过执行dex文件可在设备能运行多个虚拟机,DEX文件是专门为Android设计的字节码格式,经过优化使用的内存很小,ART主要包括的工能是,预先(AOT)和即时(JIT)编译 ,优化垃圾回收(GC),以及调试相关支持

这里的Native系统库主要包括,init孵化来的用户空间的守护进程,HAL层以及开机动画等,启动init进程(pid=1),是Linux系统的用户进程,init进程是所有用户进程的鼻祖

  • init进程会孵化出,ueventd、logd、healthd、installd、adbd、lmkd等用户守护进程
  • init进程还启动了ServiceManager(Binder的管家),bootanim(开机动画)等重要服务
  • init 进程还孵化除了Zygote进程,Zygote进程是Android中的第一个Java进程(即虚拟机进程),Zygote是所有Java进程的父进程,Zygote进程本身就是init进程孵化出来的

Framework层

  • Zygote进程,是由init进程通过解析init.rc文件后fork生成的,Zygote进程主要包括
    • 加载Zygoteinit类,注册Zygote Socket服务端套接字
    • 加载虚拟机
    • 提前加载类PreloadClasses
    • 提前加载资源PreLoadResouces
  • System Server 进程,是由Zygote fork而来,System Server是Zygote孵化出的第一个进程,System Server 负责启动和管理整个Java FrameWork,包含ActivityManagerService, WorkManagerService,PagerManagerService,PowerManagerService等服务
  • Media Server 进程,是由init fork而来,负责启动和管理整个C++FrameWork,包含AudioFlinger,Camera Service等

App层

  • Zygote 孵化出的第一个App进程是Launcher,这是用户看到的桌面App
  • Zygote 还会创建出Browser,Phone,Email等App进程,每个App至少运行在一个进程上
  • 所有的App进程都是由Zygote fork而成

Syscall && JNI

  • Native 和 KerNel之间有一层系统调用(Syscall)
  • Java 层和Native层之间的纽带JNI

重要的进程

在这里插入图片描述
Android 系统中极其重要的进程,initZygote,ServiceMager,system_server

init 进程

  • Linux系统中用户空间的第一个进程init.main

  • init进程还启动了ServiceManager进程(Binder的管家),bootanim(开机动画)等重要服务

  • init 进程还孵化除了Zygote进程Zygote进程是Android中的第一个Java进程(即虚拟机进程)Zygote是所有Java进程的父进程,Zygote进程本身就是init进程孵化出来的

Zygote进程

  • 所有App的父进程,ZygoteInit.main

  • Zygote进程,是由init进程通过解析init.rc文件后fork生成的,Zygote进程主要包括

    • 加载Zygoteinit类,注册Zygote Socket服务端套接字
    • 加载虚拟机
    • 提前加载类PreloadClasses
    • 提前加载资源PreLoadResouces
  • system_server进程,是由Zygote fork而来,System Server是Zygote孵化出的第一个进程,System Server 负责启动和管理整个Java FrameWork,包含ActivityManagerService, WorkManagerService,PagerManagerService,PowerManagerService等服务

system_server进程

系统各大服务的载体, SystemServer.main system_server进程从源码角度来看可以分为,引导服务,核心服务和其他服务

  • 引导服务(7个):ActivityManagerService、PowerManagerService、LightsService、DisplayManagerService、PackageManagerService、UserManagerService、SensorService;
  • 核心服务(3个):BatteryService、UsageStatsService、WebViewUpdateService;
  • 其他服务(70个+):AlarmManagerService、VibratorService等。

ServiceManger进程

bInder服务的大管家

ServiceManager 是Binder IPC通信过程中的守护进程,本身也是一个Binder,但是并没有采用多线程模型来跟Binder通信,而是自行编写了binder.c直接和Binder驱动来通信,并且只有一个binder_loop来读取和处理事务,这样做的好处是简单和高效 ServiceManager本身工作相对简单,其工能查询和注册服务

流程图

在这里插入图片描述
ServiceManager 集中管理系统内的所有服务,通能过权限控制进程是否有权注册服务,通过字符串来查找是否有对应的Service,由于ServiceManager进程注册了Service的死亡通知,那么服务所在的进程死亡后,只需告诉ServiceManager,每个Client通过查询ServiceManager可以获取Service的情况

启动主要包括以下几个阶段

  • 打开Binder驱动,并调用mmap()方法分配128k的内存映射空间,binder_open
  • 注册成为Binder服务的大管家binder_become_context_manager
  • 验证selinux权限,判断进程是否有权注册查看指定服务
  • 进入无限循环,处理Client发来的请求 binder_loop
  • 根据服务的名称注册服务,重复注册会移除之前的注册信息
  • 死亡通知,当所在进程死亡后,调用binder_release方法,然后调用binder_node_release,这个过程发出死亡通知回调

App进程

  • 通过Process.start启动的App进程ActivityThread.main
  • Zygote 孵化出的第一个App进程是Launcher,这是用户看到的桌面App
  • Zygote 还会创建出BrowserPhoneEmail等App进程,每个App至少运行在一个进程上
  • 所有的App进程都是由Zygote fork而成

进程与线程的区别

进程:每个App启动前必须先创建一个进程,该进程是由Zygote fork出来,进程具有独立的资源空间,用于承载App运行的各种Activity/Service组件,进程对于上层的应用层来说是完全透明的,这也是Google刻意为之,让App程序都运行在Android Runtime,大多数情况一个App运行在一个进程中,除非在AndroidManifest.xml文件中配置了Android:process,或者通过Native代码fork进程

线程:线程对于我们来说比较熟悉,比如每次new Thread().start,都会创建一个新的线程,该线程没有自己的独立空间,而是与所在的进程资源共享,从Linux来说,进程与线程都是task_struct结构体,除了是否资源共享外,没有任何区别

看一下进程创建的过程

在这里插入图片描述

  • App发起进程:如果从桌面启动应用,则发起进程便是Launcher所在的进程,当从某App启动远程进程,则发起进程是App所在的进程,发起进程首先需要通过Binder发送信息给system_server进程
  • system_server进程:调用Process.start方法,通过Socket向Zygote进程发送新建进程的请求
  • zygote进程:在执行ZygoteInit.main()后进入runSelectLoop()循环体,当有客户端连接时,便会执行ZygoteConnection.runOnce()方法,再经过层层调用后fork出新的应用进程
  • 新进程:执行handleChildProc方法,设置进程名,打开binder驱动,启动新的binder线程,设置art虚拟机参数,反射目标类的main方法,即调用ActivityThread.main()方法

Process.start()方法是阻塞方法,等待直到进程创建完成返回响应的pid,才完成该方法

在这里插入图片描述