Android 启动流程分析(一)

Android 启动流程分析(一)

面试题传送门

Android系统简介

众所周知,Android是谷歌开发的一款基于Linux的开源操作系统,下图所示为Android平台的主要组件。
Android平台概览
1.Linu内核
  Android平台的基础是Linux内核。例如,Android Runtime(ART)依靠Linux内核来执行底层功能,例如线程和低内存管理。
使用Linux内核可让Android利用主要的安全功能,并且允许设备制造商为著名的内核开发硬件驱动程序。
2.硬件抽象层(HAL)
  硬件抽象层 (HAL) 提供标准界面,向更高级别的 Java API 框架显示设备硬件功能。HAL 包含多个
库模块,其中每个模块都为特定类型的硬件组件实现一个界面,例如相机或蓝牙模块。当框架 API
要求访问设备硬件时,Android 系统将为该硬件组件加载库模块。
3.Android Runtime
  对于运行 Android 5.0(API 级别 21)或更高版本的设备,每个应用都在其自己的进程中运行,并且有其自己的 Android Runtime (ART) 实例。ART 编写为通过执行 DEX 文件在低内存设备上运行多个虚拟机,DEX 文件是一种专为 Android 设计的字节码格式,经过优化,使用的内存很少。编译工具链(例如 Jack)将 Java 源代码编译为 DEX 字节码,使其可在 Android 平台上运行。
ART 的部分主要功能包括:

  • 预先 (AOT) 和即时 (JIT) 编译

  • 优化的垃圾回收 (GC)

  • 在 Android 9(API 级别 28)及更高版本的系统中,支持将应用软件包中的 Dalvik Executable 格 式 (DEX) 文件转换为更紧凑的机器代码。

  • 更好的调试支持,包括专用采样分析器、详细的诊断异常和崩溃报告,并且能够设置观察点以监控特定字段
    在 Android 版本 5.0(API 级别 21)之前,Dalvik 是 Android Runtime。如果您的应用在 ART 上运行效果很好,那么它应该也可在 Dalvik 上运行,但反过来不一定。
    Android 还包含一套核心运行时库,可提供 Java API 框架所使用的 Java 编程语言中的大部分功能,包括一些 Java 8 语言功能。
    4.原生C/C++库
    许多核心 Android 系统组件和服务(例如 ART 和 HAL)构建自原生代码,需要以 C 和 C++ 编写的原生库。Android 平台提供 Java 框架 API 以向应用显示其中部分原生库的功能。例如,您可以通过 Android 框架的 Java OpenGL API 访问 OpenGL ES,以支持在应用中绘制和操作 2D 和 3D 图形。
    如果开发的是需要 C 或 C++ 代码的应用,可以使用 Android NDK 直接从原生代码访问某些原生平台

    5.JAVA API框架
    您可通过以 Java 语言编写的 API 使用 Android OS 的整个功能集。这些 API 形成创建 Android 应
    用所需的构建块,它们可简化核心模块化系统组件和服务的重复使用,包括以下组件和服务:

  • 丰富、可扩展的视图系统,可用以构建应用的 UI,包括列表、网格、文本框、按钮甚至可嵌入的网
    络浏览器

  • 资源管理器,用于访问非代码资源,例如本地化的字符串、图形和布局文件
    通知管理器,可让所有应用在状态栏中显示自定义提醒

  • Activity 管理器,用于管理应用的生命周期,提供常见的导航返回栈

  • 内容提供程序,可让应用访问其他应用(例如“联系人”应用)中的数据或者共享其自己的数据开发者可以完全访问 Android 系统应用使用的框架 API。
    6.系统应用
    Android 随附一套用于电子邮件、短信、日历、互联网浏览和联系人等的核心应用。平台随附的应用与用户可以选择安装的应用一样,没有特殊状态。因此第三方应用可成为用户的默认网络浏览器、短信 Messenger 甚至默认键盘(有一些例外,例如系统的“设置”应用)。

启动流程

启动流程 第一步:启动电源及系统启动
  当电源按下,引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序到RAM,然后执行
第二步:引导程序
  引导程序是在Android操作系统开始运行前的一个小程序。引导程序是运行的第一个程序,因此它是针 对特定的主板与芯片的。设备制造商要么使用很受欢迎的引导程序比如redboot、uboot、qibootloader或者开发自己的引导程序,它不是Android操作系统的一部分。引导程序是OEM厂商或者运 营商加锁和限制的地方。
引导程序分两个阶段执行。
  第一个阶段,检测外部的RAM以及加载对第二阶段有用的程序;
  第二阶段,引导程序设置网络、内存等等。这些对于运行内核是必要的,为了达到特殊的目标,引导程 序可以根据配置参数或者输入数据设置内核。
Android引导程序可以在\bootable\bootloader\legacy\usbloader找到。传统的加载器包含两个文件, 需要在这里说明:
init.s初始化堆栈,清零BBS段,调用main.c的_main()函数; main.c初始化硬件(闹钟、主板、键盘、控制台),创建linux标签
第三步:内核
Android 内核与桌面Linux的内核启动的方式差不多。内核启动时,设置缓存、被保护的存储器、计划列表、加载驱动。当内核完成系统设置,它首先在系统中寻找“init”文件,然后启动root进程或者系统的第一个进程。
第四步:init进程
init进程是Linux系统中用户空间的第一个进程,进程号固定为1。Kernel启动后,在用户空间启动init进程,并调用init中的main()方法执行init进程的职责。
第五步:启动Launcher APP

init进程

  其中init进程是Android系统中及其重要的第一个进程,主要做了下面三个事情:
1.创建和挂载启动所需的文件目录
2.初始化和启动属性服务
3.解析init.rc配置文件并启动Zygote进程
init简介

Zygote简介

  Zygote中文翻译为“受精卵”,正如其名,它主要用于孵化子进程。在Android系统中有以下两种程序:
1.java应用程序,主要基于ART虚拟机,所有的应用程序apk都属于这类2.native程序,也就是利用C或C++语言开发的程序,如bootanimation。所有的Java应用程序进程及系统服务SystemServer进程都由Zygote进程通过Linux的fork()函数孵化出来的,这也就是为什么把它称为Zygote的原因,因为他就像一个受精卵,孵化出无数子进程,而native程序则由Init程序创建启动。Zygote进程最初的名字不是“zygote”而是“app_process”,这个名字是在Android.mk文件中定义的Zgyote是Android中的第一个art虚拟机,他通过socket的方式与其他进程进行通信。这里的“其他进程”其实主要是系统进程——SystemServer

Zygote是一个C/S模型,Zygote进程作为服务端,它主要负责创建Java虚拟机,加载系统资源,启
动SystemServer进程,以及在后续运行过程中启动普通的应用程序,其他进程作为客户端向它发
出“孵化”请求,而Zygote接收到这个请求后就“孵化”出一个新的进程。比如,当点击Launcher里的
应用程序图标去启动一个新的应用程序进程时,这个请求会到达框架层的核心服务
ActivityManagerService中,当AMS收到这个请求后,它通过调用Process类发出一个“孵化”子进
程的Socket请求,而Zygote监听到这个请求后就立刻fork一个新的进程出来

位置\frameworks\base\cmds\app_process\app_main.cpp
在app_main.cpp的main函数中,主要做的事情就是参数解析. 这个函数有两种启动模式:

  • 一种是zygote模式,也就是初始化zygote进程,传递的参数有–start-system-server --socketname=zygote,前者表示启动SystemServer,后者指定socket的名称
  • 一种是application模式,也就是启动普通应用程序,传递的参数有class名字以及class带的参数
    两者最终都是调用AppRuntime对象的start函数,加载ZygoteInit或RuntimeInit两个Java类,并将之前
    整理的参数传入进去

什么是Runtime?

What is “runtime”?
在这里插入图片描述在这里插入图片描述
归纳起来的意思就是,Runtime 是支撑程序运行的基础库,它是与语言绑定在一起的。比如:

  • C Runtime:就是C standard lib, 也就是我们常说的libc。(有意思的是, Wiki会自动将“C runtime” 重定向到 “C Standard Library”).

  • Java Runtime: 同样,Wiki将其重定向到” Java Virtual Machine”, 这里当然包括Java 的支撑类库(.jar).

  • AndroidRuntime: 显而易见,就是为Android应用运行所需的运行时环境。这个环境包括以下东东:

    1. Dalvik VM: Android的Java VM, 解释运行Dex格式Java程序。每个进程运行一个虚拟机(什么叫运行虚拟机?说白了,就是一些C代码,不停的去解释Dex格式的二进制码(Bytecode),把它们转成机器码(Machine code),然后执行,当然,现在大多数的Java 虚拟机都支持JIT,也就是说,bytecode可能在运行前就已经被转换成机器码,从而大大提高了性能。过去一个普遍的认识是Java 程序比C,C++等静态编译的语言慢,但随着JIT的介入和发展,这个已经完全是过去时了,JIT的动态性运行允许虚拟机根据运行时环境,优化机器码的生成,在某些情况下,Java甚至可以比C/C++跑得更快,同时又兼具平台无关的特性,这也是为什么Java如今如此流行的原因之一吧)。
      2.Android的Java 类库, 大部分来自于 Apache Hamony, 开源的Java API 实现,如 java.lang.java.util, java.net. 但去除了AWT, Swing 等部件。
      3.JNI: C和Java互调的接口。
      4.Libc: Android也有很多C代码,自然少不了libc,注意的是,Android的libc叫 bionic C

System Server 启动流程

  System Server 是Zygote fork 的第一个Java 进程, 这个进程非常重要,因为他们有很多的系统线程,提供所有核心的系统服务
看到大名鼎鼎的WindowManager, ActivityManager了吗?对了,它们都是运行在system_server的进程里。还有很多“Binder-x”的线程,它们是各个Service为了响应应用程序远程调用请求而创建的。除此之外,还有很多内部的线程,比如 ”UI thread”, “InputReader”, “InputDispatch” 等等,我,现在我们只关心System Server是如何创建起来的。
SystemServer的main() 函数。

public static void main(String[] args) { 
     new SystemServer().run();
 }

SystemServer run方法的初始化流程

  • 初始化必要的SystemServer环境参数,比如系统时间、默认时区、语言、load一些Library等等,
  • 初始化Looper,我们在主线程中使用到的looper就是在SystemServer中进行初始化的
  • 初始化Context,只有初始化一个Context才能进行启动Service等操作,这里看一下源码:
  private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);

        final Context systemUiContext = activityThread.getSystemUiContext();
        systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
    }
}

由于篇幅原因,接下来的内容请移步:Android 启动流程分析(二)

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值