当按下Android设备上的电源键时发生了什么?

Android的启动过程是怎样的?

什么是linux内核?

桌面系统的linux内核和Android系统的linux内核之间有什么不同?

什么是Bootloader?

什么是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来源于Atom 1.6GHz x86处理器。Android设备(或者嵌入式设备,又或者基于linux的ARM设备)的启动过程与桌面版本相比有一点差别。这篇文章中,我将只解释 Android设备的启动过程。关于基于linux的桌面系统的启动过程,推荐大家阅读Inside the linux boot process这篇文章。

 

当你按下电源开关后,Android设备执行了以下步骤

%title插图%num    %title插图%num

*步:开机和系统启动

当电源按下,引导芯片代码从预定义的地方(固化在ROM)开始执行。加载Bootloader到RAM,然后执行。

 

第二步:Bootloader

Bootloader是在Android操作系统运行之前运行的一个小程序。Bootloader是运行的*个程序,所以它是针对特定的主板与芯片的。设备制造商要么使用比较流行的的Bootloader,比如redboot、uboot、qi bootloader,要么开发自己的Bootloader,它不属于Android操作系统的部分。Bootloader是OEM厂商或者运营商加锁和限制的地方。

Bootloader分两个阶段执行。*个阶段,检测外部RAM以及加载对第二阶段有用的程序,第二阶段,Bootloader设置网络、内存等等。这些对于运行内核是必要的,为了某些特定的目标,Bootloader可以向内核提供配置参数或者输入数据。

Android的Bootloader可以在<Android Source>\bootable\bootloader\legacy\usbloader目录找到。传统的加载器包含两个重要的文件,需要在这里说明:

1. init.s — 初始化堆栈,清零BBS段,调用main.c中的_main()函数

2. main.c — 初始化硬件(闹钟、主板、键盘、控制台),创建linux标签

要了解更多关于Android Bootloader的知识可以参考这个连接:

https://motorola-global-portal.custhelp.com/app/answers/detail/a_id/86208/~/bootloader-frequently-asked-questions

 

第三步:内核

Android内核的启动与桌面linux内核启动的方式类似。内核启动时开始设置高速缓存、内存保护机制、调度,加载驱动程序。当内核完成系统设置后,它首先在系统文件中寻找”init”文件,然后启动root进程或者系统的*个进程。

 

第四步:init进程

init是*个进程,我们可以管它叫root进程或者所有进程的父进程。init进程有两个任务,1. 挂载目录,比如/sys、/dev、/proc。2. 运行init.rc脚本。

· init进程可以在<Android Source>/system/core/init找到

· init.rc文件可以在<Android Source>/system/core/rootdir/init.rc找到

· readme.txt可以在<Android Source>/system/core/init/readme.txt找到

对于init.rc文件,Android中有特定的格式和规则。在Android中,我们称之为Android初始化语言。
Android初始化语言由四大类型的声明组成,分别是:Actions(动作)、Commands(命令)、Services(服务)、以及Options(选项)。
Action(动作):Action(动作)就是一些命名的命令序列,Action(动作)有一个触发器,用来决定这个Action(动作)何时发生。
语法如下

  1. n <trigger>
  2. <command>
  3. <command>
  4. <command>

Service(服务):Service(服务)是一些由init进程启动的程序、当这些Service(服务)退出时init进程会根据情况将其重启。

语法如下

  1. service <name> <pathname> [<argument>]*
  2. <option>
  3. <option>

 

Options(选项):Options(选项)是对服务的描述。它们影响init进程如何以及何时启动服务。

让我们看看默认的init.rc文件。这里我只列出了主要的事件以及服务。

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了。

 

第五步:Zygote和Dalvik

在Java中,我们知道不同的虚拟机实例会为不同的应用分配不同的内存。假如Android应用应该尽可能快地启动,如果Android系统为每一个应用启动不同的Dalvik虚拟机实例,就会消耗大量的内存和时间。因此,为了克服这个问题,Android系统创造了”Zygote”。Zygote使得Dalvik虚拟机共享代码、低内存占用和*小的启动时间成为可能。Zygote是一个虚拟机进程,正如我们在前一个步骤所说,它在系统启动时启动。 Zygote预加载并且初始化核心类库。通常,这些核心类都是只读的,是Android SDK或者核心框架的一部分。在Java虚拟机中,每一个实例都有它自己的核心库类文件和堆对象的拷贝。

Zygote加载进程

1. 加载ZygoteInit类,源代码:<Android Source>/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

2. registerZygoteSocket() — 为zygote命令连接注册一个服务器套接字

3. preloadClasses()—“preloaded-classes”是一个简单的包含一系列需要预加载类的文本文件,你可以在<Android Source>/frameworks/base找到“preloaded-classes”文件。

4. preloadResources() — preloadResources意味着本地主题和布局以及android.R文件中包含的所有东西都会用这个方法加载。

在这个时候,你可以看到开机动画。

 

第六步:系统服务或服务

完成了上面几步之后,Runtime请求Zygote启动系统服务。系统服务同时使用native以及java编写,系统服务可以认为是一个进程。同一个系统服务可以以System Services的形式在Android SDK获得。系统服务包含了所有的System Services。

Zygote创建新的进程去启动系统服务。你可以在ZygoteInit类的”startSystemServer”方法中找到源代码。

核心服务:

1. 启动电源管理器

2. 创建Activity管理器

3. 启动电话注册

4. 启动包管理器

5. 设置Activity管理服务为系统进程

6. 启动上下文管理器

7. 启动系统Context Providers

8. 启动电池服务

9. 启动定时管理器

10. 启动传感服务

11. 启动窗口管理器

12. 启动蓝牙服务

13. 启动挂载服务

其他服务:

1. 启动状态栏服务

2. 启动硬件服务

3. 启动网络状态服务

4. 启动连接服务

5. 启动通知管理器

6. 启动设备存储监视服务

7. 启动定位管理器

8. 启动搜索服务

9. 启动剪切板服务

10. 启动登记服务

11. 启动壁纸服务

12. 启动音频服务

13. 启动耳机监听

14. 启动AdbSettingsObserver(处理adb命令)。

 

第七步:启动完成

一旦系统服务在内存中运行起来,Android就完成了启动过程。在这个时候“ACTION_BOOT_COMPLETED”广播就会发出去。