android启动过程
⑴ Android启动过程深入解析
当按下Android设备电源键时究竟发生了什么?
Android的启动过程是怎么样的?
什么是linux内核?
桌面系统linux内核与Android系统linux内核有什么区别?
什么是引导装载程序?
什么是Zygote?
什么是X86以及ARM linux?
什么是init.rc?
什么是系统服务?
当我们想到Android启动过程时,脑海中总是冒出很多疑问。本文将介绍Android的启动过程,希望能帮助你找到上面这些问题的答案。
Android是一个基于Linux的开源操作系统。x86(x86是一系列的基于intel 8086 CPU的计算机微处理器指令集架构)是linux内核部署最常见的系统。然而,所有的Android设备都是运行在ARM处理器(ARM 源自进阶精简指令集机器,源自ARM架构)上,除了英特尔的Xolo设备(http://xolo.in/xolo-x900-features)。Xolo来源自凌动1.6GHz x86处理器。Android设备或者嵌入设备或者基于linux的ARM设备的启动过程与桌面版本相比稍微有些差别。这篇文章中,我将解释Android设备的启动过程。深入linux启动过程是一篇讲桌面linux启动过程的好文。
当你按下电源开关后Android设备执行了以下步骤。
此处图片中step2中的一个单词拼写错了,Boot Loaeder应该为Boot Loader(多谢@jameslast 提醒)
第一步:启动电源以及系统启动
当电源按下,引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序到RAM,然后执行。
第二步:引导程序
引导程序是在Android操作系统开始运行前的一个小程序。引导程序是运行的第一个程序,因此它是针对特定的主板与芯片的。设备制造商要么使用很受欢迎的引导程序比如redboot、uboot、qi bootloader或者开发自己的引导程序,它不是Android操作系统的一部分。引导程序是OEM厂商或者运营商加锁和限制的地方。
引导程序分两个阶段执行。第一个阶段,检测外部的RAM以及加载对第二阶段有用的程序;第二阶段,引导程序设置网络、内存等等。这些对于运行内核是必要的,为了达到特殊的目标,引导程序可以根据配置参数或者输入数据设置内核。
Android引导程序可以在找到。
传统的加载器包含的个文件,需要在这里说明:
init.s初始化堆栈,清零BBS段,调用main.c的_main()函数;
main.c初始化硬件(闹钟、主板、键盘、控制台),创建linux标签。
更多关于Android引导程序的可以在这里了解。
第三步:内核
Android内核与桌面linux内核启动的方式差不多。内核启动时,设置缓存、被保护存储器、计划列表,加载驱动。当内核完成系统设置,它首先在系统文件中寻找”init”文件,然后启动root进程或者系统的第一个进程。
第四步:init进程
init是第一个进程,我们可以说它是root进程或者说有进程的父进程。init进程有两个责任,一是挂载目录,比如/sys、/dev、/proc,二是运行init.rc脚本。
init进程可以在/system/core/init找到。
init.rc文件可以在/system/core/rootdir/init.rc找到。
readme.txt可以在/system/core/init/readme.txt找到。
对于init.rc文件,Android中有特定的格式以及规则。在Android中,我们叫做Android初始化语言。
Action(动作):动作是以命令流程命名的,有一个触发器决定动作是否发生。
语法
1
2
3
4
5
; html-script: false ]
on <trigger>
<command>
<command>
<command>
Service(服务):服务是init进程启动的程序、当服务退出时init进程会视情况重启服务。
语法
1
2
3
4
5
; html-script: false ]
service <name> <pathname> [<argument>]*
<option>
<option>
...
Options(选项)
选项是对服务的描述。它们影响init进程如何以及何时启动服务。
咱们来看看默认的init.rc文件。这里我只列出了主要的事件以及服务。
Table
Action/Service
描述
on early-init
设置init进程以及它创建的子进程的优先级,设置init进程的安全环境
on init
设置全局环境,为cpu accounting创建cgroup(资源控制)挂载点
on fs
挂载mtd分区
on post-fs
改变系统目录的访问权限
on post-fs-data
改变/data目录以及它的子目录的访问权限
on boot
基本网络的初始化,内存管理等等
service servicemanager
启动系统管理器管理所有的本地服务,比如位置、音频、Shared preference等等…
service zygote
启动zygote作为应用进程
在这个阶段你可以在设备的屏幕上看到“Android”logo了。
第五步
在java中,我们知道不同的虚拟机实例会为不同的应用分配不同的内存。假如Android应用应该尽可能快地启动,但如果Android系统为每一个应用启动不同的Dalvik虚拟机实例,就会消耗大量的内存以及时间。因此,为了克服这个问题,Android系统创造了”Zygote”。Zygote让Dalvik虚拟机共享代码、低内存占用以及最小的启动时间成为可能。Zygote是一个虚拟器进程,正如我们在前一个步骤所说的在系统引导的时候启动。Zygote预加载以及初始化核心库类。通常,这些核心类一般是只读的,也是Android SDK或者核心框架的一部分。在Java虚拟机中,每一个实例都有它自己的核心库类文件和堆对象的拷贝。
Zygote加载进程
加载ZygoteInit类,源代码:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
registerZygoteSocket()为zygote命令连接注册一个服务器套接字。
preloadClassed “preloaded-classes”是一个简单的包含一系列需要预加载类的文本文件,你可以在/frameworks/base找到“preloaded-classes”文件。
preloadResources() preloadResources也意味着本地主题、布局以及android.R文件中包含的所有东西都会用这个方法加载。
在这个阶段,你可以看到启动动画。
第六步:系统服务或服务
完成了上面几步之后,运行环境请求Zygote运行系统服务。系统服务同时使用native以及java编写,系统服务可以认为是一个进程。同一个系统服务在Android SDK可以以System Services形式获得。系统服务包含了所有的System Services。
Zygote创建新的进程去启动系统服务。你可以在ZygoteInit类的”startSystemServer”方法中找到源代码。
核心服务:
启动电源管理器;
创建Activity管理器;
启动电话注册;
启动包管理器;
设置Activity管理服务为系统进程;
启动上下文管理器;
启动系统Context Providers;
启动电池服务;
启动定时管理器;
启动传感服务;
启动窗口管理器;
启动蓝牙服务;
启动挂载服务。
其他服务:
启动状态栏服务;
启动硬件服务;
启动网络状态服务;
启动网络连接服务;
启动通知管理器;
启动设备存储监视服务;
启动定位管理器;
启动搜索服务;
启动剪切板服务;
启动登记服务;
启动壁纸服务;
启动音频服务;
启动耳机监听;
启动AdbSettingsObserver(处理adb命令)。
第七步:引导完成
一旦系统服务在内存中跑起来了,Android就完成了引导过程。在这个时候“ACTION_BOOT_COMPLETED”开机启动广播就会发出去。
⑵ Android输入法IMMS服务启动流程(3)(启动IMS应用)
接上一篇,IMMS设置当前默认输入法为LatinIME输入法后,调用onCreate方法,然后会调用startInputInnerLocked启动输入法LatinIME的服务
本章节主要分析,onCreate生命周期中,各个流程调用
bindServiceAsUser启动的服务是LatinIME
如上图流程图,服务启动后,会调用到InputMethodManagerService的方法
该流程的主要逻辑:
完成对mMethodList和mMethodMap的数据初始化;检查当前默认的输入法(LatinIME)服务是否存在,很明显,经过systemrunning过程以后,
mMethodMap已经包含了LatinIME,因此不会重复执行选择和设定另外输入法为默认输入法的操作
该方法主要是检查默认的LatinIME是否是可用的可用的输入法,如果不可用,则设置为可用;
对应的settingprovider字段为:
经过以上流程后,默认输入法依然为LatinIME输入法,该流程的主要作用为,将启动的输入法应用更新到可用列表enabled_input_methods中;
不过,目前默认的输入法依然为LatinIME输入法,跟重启手机前,我们设置的输入法(搜狗输入法)依然不一致
下一篇文章,我们研究下,输入法启动过程中的onBind和onServiceConnected流程
⑶ Android启动优化概述
Android启动应用, 按 官方说法 分为冷启动, 温启动和热启动.
具体的定义可以看官方文档, 简单地说
一般我们只需要关注冷启动即可.
要想启动快, 硬件性能必然有影响, 在硬件一定的前提下, 我们要尽量 降低启动应用时CPU的负载 , 让CPU有更多的算力投入到启动流程中:
在做好一些基本原则后, 接着看具体的流程优化点
在应用进程创建后, 首先必然是加载类, 此时一些静态变量就会初始化了, 因此我们应该
类加载完毕后就是创建 Application 实例了, 因此我们应该
之后会先创建 ContentProvider 和执行 ContentProvider.onCreate() , 因此我们应该
跟接着就会执行 Application.onCreate() 等方法, 因此我们应该
接着就进入 Activity 环节.
同样第一步会是创建实例, 因此我们应该
在 Activity 进程生命周期后, 第一步就是渲染(inflate)布局, 我们应该
在应用启动的瞬间, 系统服务会先展示一个空白窗口, 等待应用第一帧绘制完毕后, 再从该窗口切换到应用, 如果启动耗时较长, 就会明显看到白屏, 对于这一点, 常见的操作有
可以使用IdleHandler, 在主线程空闲时再执行某些不重要的操作
实际上异步初始化只是不阻塞主线程, 但是子线程一样会占用CPU资源, 让主线程的执行时间变少, 所以不应该盲目地将所有工作放到子线程.
优化做到最后, 就是在系统流程上做文章了
原理是将启动时加载的类放到主dex,提升了这些类的内聚,让更多的类满足pre-verify的条件,在安装时就做了校验和优化,以减少首次加载的耗时,从而优化冷启动耗时。
Redex 初探与 Interdex:Andorid 冷启动优化
应用启动过程中会从apk压缩包中读取文件, 该优化的原理是利用Linux中的Pagecache机制, 让启动过程会用到的文件尽可能进入缓存中, 减少磁盘IO次数
支付宝 App 构建优化解析:通过安装包重排布优化 Android 端启动性能
在Dalvik VM(Android5.0以前)加载类的时候会有一个类校验过程, 它需要校验方法的每一个指令, 是一个比较耗时的过程, 可以通过Hook去掉类加载过程中的类验证过程. 不过对于ART(Android5.0之后)来说, 这个过程在安装时已经做了, 所以用处不大.
不进入冷启动, 就不用优化了~
这个Android Studio自带的工具, 可以看到启动过程中详细的方法执行流程, 但是采集数据本身会影响方法执行, 所以不能准确判断每个方法的耗时, 但是仍可以判断哪个方法相对来说耗时.
这个工具的好处是可以自定义事件, 可以指定需要采集的数据集, 可以看到线程间的状态等.
启动优化的一个关键点在于定义启动结束的点, 以及如何测量启动时间.
在Android4.4以上, 系统进程会提供一个类似 ActivityManager: Displayed ***: +3s534ms 的日志, 表示从启动进程到首次绘制完毕所用的时间.
应用可以在任何时候调用该方法, 触发系统打印类似 system_process I/ActivityManager: Fully drawn {package}/.MainActivity: +1s54ms 的日志
应用可以通过 ViewTreeObserver 来监听绘制前回调来判断第一帧的绘制时机, 或者直接在控件树的末尾加一个简单的View, 它 onDraw 调用时即表示页面(差不多)绘制完毕.
应用启动过程可以参考 Android Vitals Series' Articles 系列文章
⑷ Android 10.0 ActivityManagerService的启动流程
我们讲完了SystemServer的启动过程,本节主要来讲解ActivityManagerService的启动过程。ActivityManagerService简称AMS,管理Activity行为,控制Activity的生命周期,派发消息事件,内存管理等功能。
ActivityManagerService启动由SystemServer中startBootstrapService启动
ATM启动最终调用的是ActivityTaskManagerService.Lifecycle.onStart()来启动ATM服务的
源码:ActivityTaskManagerService.java#Lifecycle.class
将ActivityTaskManagerInternal添加到本地服务的全局注册表中。
ActivityTaskManagerInternal为抽象类,其实现类为ActivityTaskManagerService#LocalService.class
构造函数初始化主要工作就是初始化一些变量,供之后的service,broadcast,provider的管理和调度
start中做了两件事
AMS的systemReady处理分为三个阶段
同时获取一些配置参数。 需要注意的是,由于只有Java进程才会向AMS注册,而一般的Native进程不会向AMS注册,因此此处杀死的进程是Java进程。
主要是调用一些关键服务的初始化函数,然后杀死那些没有FLAG_PERSISTENT 却在AMS启动完成前已经存在的进程,同时获取一些配置参数。需要注意的是,由于只有Java进程才会向AMS注册,而一般的Native进程不会向AMS注册,因此此处杀手的进程是Java进程。
执行goingCallback的处理,主要的工作就是通知一些服务可以进行systemReady相关的工作,并进行启动服务或应用进程的工作
监控Native的crash,启动WebView,执行一些服务的systemReady和systemRunning方法
启动Home Activity,当启动结束,发送ACTION_BOOT_COMPLETED广播时,AMS的启动过程告一段落
启动Home Activity
AMS的启动主要经历了如下几个阶段:
⑸ Android系统启动之init.rc文件解析过程
第一篇: Android系统启动之bootloader
第二篇: Android系统启动之Init流程(上)
第三篇: Android系统启动之Init流程(下)
第四篇: Android系统启动之init.rc文件解析过程
第五篇: Android系统启动之zyogte进程
第六篇: Android系判哗统启动之zyogte进程java(上)
第七篇: Android系统启动之zyogte进程java(下)
第八篇: Android系统启动之SystemServer
Android init.rc文件由系统第一个启动的init程序解析。是启动系统服务使用的文件。
主要包含了四种类型的语句:
Action和services显式声明了一个语句块,而commands和options属于最近声明的语句块。
在第一个语句块之前 的commands和options会被忽略.
基本规则如下:
动掘蚂行作表示了一组命令(commands)组成.动作包括一个触发器,决定了何时运行这个动作。
注意: 当触发器的条件满足时,这个动作会被增加到已被运行的队列尾。假设此动作在队列中已经存在,那么它将不会运行.
一个动作所包括的命令将被依次运行。
在"动作"(action)里面的,on后面物隐跟着的字符串是触发器(trigger),trigger是一个用于匹配某种事件类型的字符串,它将对应的Action的执行。
触发器(trigger)有几种格式:
常见的格式:
command是action的命令列表中的命令,或者是service中的选项 onrestart 的参数命令.
命令将在所属事件发生时被一个个地执行.
常见命令:
服务是指那些须要在系统初始化时就启动或退出时自己主动重新启动的程序.
解释一下各个参数:
options是Service的修订项。它们决定一个服务何时以及如何运行.
使用例子:
源码路径 system/core/init/init.cpp 中:
开始解析rc文件.
ParseConfig函数在文件 core/init/init_parser.cpp 140行:
ParseConfigFile函数:
Android init.rc文件浅析
安卓系统启动--3init.rc解析
init.rc深入学习
⑹ Android 从点击应用图标到界面显示的过程
[转] 一篇文章看明白 Android 从点击应用图标到界面显示的过程 (遵循CC 4.0 BY-SA版权协议)
从点击桌面应用图标到应用显示的过程我们再熟悉不过了,下面我们来分析下这个过程都做了什么。
本文主要对以下问题分析:
如不了解 Android 是如何从开机到 Launcher 启动的过程,请先阅读 Android - 系统启动过程
我们知道 Android 系统启动后已经启动了 Zygote,ServiceManager,SystemServer 等系统进程;ServiceManager 进程中完成了 Binder 初始化;SystemServer 进程中 ActivityManagerService,WindowManagerService,PackageManagerService 等系统服务在 ServiceManager 中已经注册;最后启动了 Launcher 桌面应用。
其实 Launcher 本身就是一个应用程序,运行在自己的进程中,我们看到的桌面就是 Launcher 中的一个 Activity。
应用安装的时候,通过 PackageManagerService 解析 apk 的 AndroidManifest.xml 文件,提取出这个 apk 的信息写入到 packages.xml 文件中,这些信息包括:权限、应用包名、icon、apk 的安装位置、版本、userID 等等。packages.xml 文件位于系统目录下/data/system/packages.xml。
同时桌面 Launcher 会为安装过的应用生成不同的应用入口,对应桌面上的应用图标,下面分析点击应用图标的到应用启动的过程。
点击 Launcher 中应用图标将会执行以下方法
在 system_server 进程中的服务端 ActivityManagerService 收到 START_ACTIVITY_TRANSACTION 命令后进行处理,调用 startActivity() 方法。
从 Launcher 点击图标,如果应用没有启动过,则会 fork 一个新进程。创建新进程的时候,ActivityManagerService 会保存一个 ProcessRecord 信息,Activity 应用程序中的AndroidManifest.xml 配置文件中,我们没有指定 Application 标签的 process 属性,系统就会默认使用 package 的名称。每一个应用程序都有自己的 uid,因此,这里 uid + process 的组合就可以为每一个应用程序创建一个 ProcessRecord。每次在新建新进程前的时候会先判断这个 ProcessRecord 是否已存在,如果已经存在就不会新建进程了,这就属于应用内打开 Activity 的过程了。
进程创建成功切换至 App 进程,进入 app 进程后将 ActivityThread 类加载到新进程,并调用 ActivityThread.main() 方法
此时只创建了应用程序的 ActivityThread 和 ApplicationThread,和开启了 Handler 消息循环机制,其他的都还未创建, ActivityThread.attach(false) 又会最终到 ActivityMangerService 的 attachApplication,这个工程其实是将本地的 ApplicationThread 传递到 ActivityMangerService。然后 ActivityMangerService 就可以通过 ApplicationThread 的代理 ApplicationThreadProxy 来调用应用程序 ApplicationThread.bindApplication,通知应用程序的 ApplicationThread 已和 ActivityMangerService 绑定,可以不借助其他进程帮助直接通信了。此时 Launcher 的任务也算是完成了。
在 system_server 进程中的服务端 ActivityManagerService 收到 ATTACH_APPLICATION_TRANSACTION 命令后进行处理,调用 attachApplication()。
发送送完 SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION 命令,还会发送 BIND_APPLICATION_TRANSACTION 命令来创建 Application。
在 app 进程中,收到 BIND_APPLICATION_TRANSACTION 命令后调用 ActivityThread.bindApplication()。
ApplicationThreadProxy.bindApplication(…) 会传来这个应用的一些信息,如ApplicationInfo,Configuration 等,在 ApplicationThread.bindApplication 里会待信息封装成AppBindData,通过
将信息放到应用里的消息队列里,通过 Handler 消息机制,在 ActivityThread.handleMeaasge 里处理 H.BIND_APPLICATION 的信息,调用 AplicationThread.handleBindApplication。
Instrumentation:
这时 Application 就创建好了,这点很重要,很多资料里说 Application 是在performLaunchActivity() 里创建的,因为 performLaunchActivity() 也有mInstrumentation.newApplication 这个调用,newApplication() 函数中可看出会先判断是否以及创建了 Application,如果之前已经创建,就返回已创建的 Application 对象。
上面 fork 进程时会发送 SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION 命令,在 app 进程中,收到 SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION 命令后调用 ApplicationThread.scheleLaunchActivity()。
与 Window 进行关联,具体过程详见: Activity,Window,View 之间的关系
Activity 的整体启动流程如图所示:
⑺ Android的文件系统和分区表谁能给我详细地讲一讲
Android系统启动流程如下:
1、启动电源以及系统启动
当电源按下时引导芯片代码从预定义的地方(固化在ROM)开始执行。加载引导程序BootLoader到RAM,然后执行。
2、引导程序BootLoader
引导程序BootLoader是在Android操作系统开始运行前的一个小程序,它的主要作用使把系统OS拉起来并运行。
3、Linux内核启动
当内核启动时,设置缓存、被保护存储器、计划列表、加载驱动。当内核完成系统设置时,它首先在系统文件中寻找init.rc文件,并启动init进程。
4、init进程启动
初始化和启动属性服务,并且启动Zygote进程。
5、Zygote进程启动
创建Java虚拟机并为Java虚拟机注册JNI方法,创建服务器端Socket,启动SystemServer进程。
6、SystemServer进程启动
启动Binder线程池和SystemServiceManager,并且启动各种系统服务。
7、Launcher启动
被SystemServer进程启动的AMS会启动Launcher,Launcher启动会将已安装的快捷图标显示在界面上。