Android启动过程深入解析
本文由 伯乐在线 - 云海之巅 翻译。未经许可,禁止转载!
英文出处:kpbird。欢迎加入翻译小组。
- 当按下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引导程序可以在\bootable\bootloader\legacy\usbloader找到。
传统的加载器包含的个文件,需要在这里说明:
- 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初始化语言。
Android初始化语言由四大类型的声明组成,即Actions(动作)、Commands(命令)、Services(服务)、以及Options(选项)。
Action(动作):动作是以命令流程命名的,有一个触发器决定动作是否发生。
语法
| 
 1 
2 
3 
4 
 | 
on <trigger>    <command>    <command>    <command> | 
Service(服务):服务是init进程启动的程序、当服务退出时init进程会视情况重启服务。
语法
| 
 1 
2 
3 
4 
 | 
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”是一个简单的包含一系列需要预加载类的文本文件,你可以在<Android Source>/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启动过程深入解析的更多相关文章
- Android启动过程深入解析【转】
		
转自:http://www.open-open.com/lib/view/open1403250347934.html 当按下Android设备电源键时究竟发生了什么? Android的启动过程是怎么 ...
 - Android 6.0启动过程具体解析
		
在之前的一篇文章中.从概念上学习了Andoird系统的启动过程.Android系统启动过程学习 而在这篇文章中,我们将从代码角度细致学习Android系统的启动过程,同一时候,学习Android启动过 ...
 - Android程序启动过程深入解析
		
当按下Android设备电源键时究竟发生了什么? Android的启动过程是怎么样的? 什么是Linux内核? 桌面系统linux内核与Android系统linux内核有什么区别? 什么是引导装载程序 ...
 - Android 核心分析 之八Android 启动过程详解
		
Android 启动过程详解 Android从Linux系统启动有4个步骤: (1) init进程启动 (2) Native服务启动 (3) System Server,Android服务启动 (4) ...
 - Android启动过程以及各个镜像的关系
		
Android启动过程 Android在启动的时候,会由UBOOT传入一个init参数,这个init参数指定了开机的时候第一个运行的程序,默认就是init程序,这个程序在ramdisk.img中.可以 ...
 - Android(java)学习笔记162:Android启动过程(转载)
		
转载路径为: http://blog.jobbole.com/67931/ 1. 关于Android启动过程的问题: 当按下Android设备电源键时究竟发生了什么? Android的启动过程是怎么样 ...
 - Android(java)学习笔记105:Android启动过程(转载)
		
转载路径为: http://blog.jobbole.com/67931/ 1. 关于Android启动过程的问题: 当按下Android设备电源键时究竟发生了什么? Android的启动过程是怎么样 ...
 - Android 启动过程简析
		
首先我们先来看android构架图: android系统是构建在linux系统上面的. 所以android设备启动经历3个过程. Boot Loader,Linux Kernel & Andr ...
 - Android系统启动过程全解析
		
Android系统是一款基于Linux的移动操作系统,那么Android是如何启动起来的呢?本文就详细阐述Android系统的启动过程. 从内核之上,我们首先应该从文件系统的init开始,因为 ini ...
 
随机推荐
- Spring(十三):使用工厂方法来配置Bean的两种方式(静态工厂方法&实例工厂方法)
			
通过调用静态工厂方法创建Bean 1)调用静态工厂方法创建Bean是将对象创建的过程封装到静态方法中.当客户端需要对象时,只需要简单地调用静态方法,而不需要关心创建对象的具体细节. 2)要声明通过静态 ...
 - 【机器学习】Logistic Regression 的前世今生(理论篇)
			
Logistic Regression 的前世今生(理论篇) 本博客仅为作者记录笔记之用,不免有非常多细节不正确之处. 还望各位看官能够见谅,欢迎批评指正. 博客虽水,然亦博主之苦劳也. 如需转载,请 ...
 - JavaScript中一个对象如何继承另外一个对象
			
如题,JavaScript中一个对象a如何继承另外一个对象b.即将b中的属性和方法复制到a中去. 面试中遇到了这个问题,当时脑子里的想法是: 1.除了循环遍历复制,还能怎样 2.javascript中 ...
 - 使用Robot Framework做接口测试
			
http://chuansong.me/n/1858477 1.RF框架 1.1 RF框架介绍Robot Framework 框架是一个通用的测试框架,一直是由诺西网络(Nokia Siemens N ...
 - Redis 实现队列http://igeekbar.com/igeekbar/post/436.htm
			
场景说明: ·用于处理比较耗时的请求,例如批量发送邮件,如果直接在网页触发执行发送,程序会出现超时 ·高并发场景,当某个时刻请求瞬间增加时,可以把请求写入到队列,后台在去处理这些请求 ·抢购场景,先入 ...
 - Android实战技巧:如何在ScrollView中嵌套ListView
			
前几天因为项目的需要,要在一个ListView中放入另一个ListView,也即在一个ListView的每个ListItem中放入另外一个ListView.但刚开始的时候,会发现放入的小ListVie ...
 - SpringBoot报错 : Whitelabel Error Page
			
添加了一个Controller类,本来想试下Spring MVC是否可以正常运行,结果报错,Controller类的内容: @RestController public class Test1Cont ...
 - ZH奶酪:PHP 使用DOMDocument操作XML
			
原文链接:http://my.oschina.net/zhangb081511/blog/160113 PHP写XML方法很多,这里主要介绍一下DOMDocument的用法,跟 JS大体上相同,其实非 ...
 - 微信小程序 - template和include详细描述
			
演示 index.wxml <!-- 内部模板 --> <template name="all"> {{a}} {{b}} </template> ...
 - 树莓派系统(Debain)中设置SSH服务开机自启动
			
一.方式: 禁用命令:sudo update-rc.d ssh disable 启用命令:sudo update-rc.d ssh enable 二.chkconfig的方式: 1.安装:apt-ge ...