Android系统开机主要经历三个阶段:

  1. bootloader启动
  2. Linux启动
  3. Android启动

启动文件:

对于机器从通电到加载Linux系统一般需要三个文件:bootloader(引导文件)、kernel(内核文件)、rootfs (根文件系统 能让操作系统正常运行的文件夹和文件的大集合,在Android中是ramdisk)。这些文件在ROM Build的时候会编译成IMAGE的形式打包到ROM中。

Android系统主要分为两个区。system分区包含有Android运行时框架、系统APP以及预装的第三方APP等;boot分区包含有kernel。刷入到system分区和boot分区的两个镜像称为system.img和boot.img

Ramdisk 是将一部分固定大小的RAM空间模拟出硬盘分区,在引导时内核以只读方式挂载它。它并非一个实际的文件系统,而是一种将实际的文件系统装入内存的机制,并且可以作为根文件系统。将一些经常被访问而又不会更改的文件 ( 如只读的根文件系统 ) 通过 Ramdisk 放在内存中,可以明显地提高系统的性能。但是对于这些文件的修改,掉电后就会丢失,只能修改IMG并重刷。

ramdisk.img是一个只读image分区,包含了Linux主要的目录机构,可以单独编译或编译到内核。主要是存放android启动后第一个用户进程init可执行文件和init.*.rc等相关启动脚本以及sbin目录下的adbd工具。而system, data,dev,proc,sys等目录都是空的,用来挂载对应的分区的。

通过刷机可以将这些IMG文件刷入到手机的Flash存储中。而一般手机Flash主要有两类:

NOR Flash:特点是芯片内执行(XIP, eXecute In Place),这样应用程序可以直接在flash闪存内运行,不必再把代码读到系统RAM中。NOR的传输效率很高,在1~4MB的小容量时具有很高的成本效益,但是很低的写入和擦除速度大大影响了它的性能。

NAND Flash

NAND结构能提供极高的单元密度,可以达到高存储密度,并且写入和擦除的速度也很快。

 

启动流程:

1. Bootloader启动

bootloader是嵌入式系统的引导加载程序,是系统通电后运行的第一段程序,主要作用是引导操作系统,类似PC上的BIOS程序。一般会分为BL1和BL2两个阶段,分别是初始化硬件和加载操作系统。基本功能如下:

a)        
硬件设备初始化:主要包括屏蔽所有中断,设置CPU的速度和时钟频率,关闭处理器内部指令,数据cache等;

b)        
初始化RAM:
设置CPU寄存器,为加载Kernel做准备;

c)        
初始化串口:
主要用来进行交互,输出调试信息;

d)        
检查CPU类型: Linux内核启动时需要根据CPU类型调用相应的初始化程序;

e)        
设置Linux启动参数: Linux会根据参数进行相应的初始化操作;

f)         
调用Linux Kernel Image:加载kernel和ramdisk到RAM指定地址,并转跳到此地址开始执行Kernel的第一条指令。

启动bootloader过程:

当机器通电后,ARM CPU的PC(程序计数器)寄存器的值是0x0,于是CPU会从这个地址取指令执行,所有嵌入式设备都会把相关的ROM或Flash映射到这个地址(通过硬件引脚电平高低实现http://blog.csdn.net/yapingmcu/article/details/7248890)。如果bootloader存放在NOR Flash中,则0x0就是Flash中第一条指定地址,一般BL1在NOR中执行,而BL2加载到RAM执行提高速度; 如果存放在NAND
Flash中,则需要将BL1加载到RAM执行,然后加载并执行BL2,不同芯片加载BL1的这个过程是不同的。

Bootloader还支持交互式启动,在BL1完成后不是马上执行BL2,而是等待用户操作,这种启动模式就叫做fastboot。

2. Linux启动

a)        
Kernel镜像zImage解压

b)        
Kernel的汇编启动: 根据BL中传递的参数,执行相应的初始化操作(与硬件平台相关),主要的一步是建立页表,为内核建立4M的内存映射

c)        
Kernel 的C启动:执行init/main.c中start_kernel方法。它主要完成剩余的与硬件平台相关的初始化操作。初始化核心进程调度器和中断处理函数、创建文件和系统缓存、初始化内存管理MMU、初始化内存。

d)        
rest_init()函数,kernel_thread()启动第一个内核线程执行kernel_init()

i.             
加载系统设备和驱动程序,并进行初始化

                      
ii.             
加载Binder,创建/dev/binder设备文件,并注册为misc设备

iii.             
将ramdisk作为rootfs挂载到根目录/

iv.             
调用execve()创建系统的第一个用户进程Init (/system/core/init/init.c)

v.             
解析并执行Init.rc文件,启动系统服务,此时线程进入用户空间运行。

3. Android启动

a)        
解析并执行init.rc文件(\system\core\rootdir\init.rc) (Android系统启动过程比PC要简单,init.rc与PC的内容也不相同,包含了4种不同操作称为Android
Init Launage 在system/core/Init/readme.txt有具体描述)

b)        
创建dev、proc、system、data等目录并挂载对应的分区,设置目录和文件的用户和权限。

c)        
执行四种操作中的Action和Commands,然后启动Native 空间的Service如console、adbd、vold、netd、media、ril-daemon、surfaceflinger、ril-daemon等等。

d)        
启动ServiceManager服务:是Binder的守护进程,主要负责整个系统service的管理,系统中所有的服务都必须在SMgr中注册,获取服务是也需要向Smgr申请,通过它获得远程服务的Binder实体。Android的IPC由Client、Service、ServiceManager和Binder组成,Binder驱动完成实际IPC功能,而SMgr则对service进行管理。

(frameworks\native\cmds\servicemanager\service_manager.c)

e)        
启动Zygote服务: Zygote进程也叫孵化进程,Android世界中所有的进程都是从此进程孵化而来(fork()),它负责应用程序框架层的其它进程的创建和启动工作。

(frameworks/base/cmds/app_process/app_main.cpp) (Android L中启动Zygote的脚本不在init.rc文件中,而是有单独的init.zygote_xx.rc文件来启动,用于支持64位操作系统)

i.             
Zygote创建AppRuntime并启动,调用startVm,里面会调用JNI_CreateJavaVM来启动Davlik虚拟机。并加载需要的库和jar包,这样每次fork出新的进程就不需要在加载VM了。

ii.             
调用startReg()注册Android的JNI方法

iii.             
通过JNI从Native层调用Java层的com.android.internal.os.ZygoteInit类的main函数,这个函数主要做了下面3件事情:

  1. Zygote注册一个socket用了进行进程通信,当我们需要启动一个Android应用程序时,AMS会通过Socket通知Zygote为这个应用程序创建一个新的进程。
  2. Zygote进程fork出一个SystemServer进程,SystemServer进程负责启动系统的关键服务,如包管理服务PackageManagerService和应用程序组件管理服务ActivityManagerService。具体运行过程见f
  3. Zygote执行runSelectLoopMode进入循环来监听socket请求

f)         
运行SystemServer:被创建后会运行handleSystemServerProcess(),
此进程将负责启动其他的Android服务

(frameworks\base\services\java\com\android\server\SystemServer.java)

i.             
关闭进程中的socket,因为是从Zygote进程fork出来的,但不需要使用。

ii.             
加载libandroid_servers.so

iii.             
执nativeInit ()启动Native空间的Sensor Service,并注册到ServiceManager (frameworks/base/services/core/jni/com_android_server_SystemServer.cpp)

iv.             
执行ServerThread.initAndLoop()启动Java空间的Service,并注册到ServiceManage(主要包括AMS/WMS/ConnectivityService/InputManagerService等)

v.             
调用每个service的systemReady方法通知service系统已经启动完成

vi.             
调用Looper.loop() 在主线程启动消息循环

PS: 我看Kitkat代码和网上介绍的老版本不太一样,老版本使用init1()和init2()两个函数来启动Native和Java的Service,而且init1中启动了很多service,主要包括:Sensor/AudioFlinger/MediaPlayer/Camera/AudioPolicy,而这里只启动了sensor的服务。还不知道其他服务在那里启动。

g)        
启动Home:

i.             
AMS的systemReady方法被调用,其中会调用resumeTopActivityLocked()

ii.             
最终会调用到ActivityStack.java中的resumeTopActivityLocked

iii.             
发现没有其他任何的Activity,调用ActivityStackSupervisor.resumeHomeActivity

iv.             
getHomeIntent获取intent, Intent的category为Intent.CATEGORY.HOME,然后调用AMS.startHomeActivityLocked传递Intent

v.             
调用ActivityStackSupervisor. startHomeActivity
, 调用startActivityLocked()

vi.             
通过resolveActivityInfo函数向 PackageManagerService 查询 CATEGORY 类型为 HOME 的应用

vii.             
最后AMS会通知Zygote启动一个新的进程

h)        
至此Android系统启动过程全部完成

 

 

参考:

 

ROM、PROM、EPROM、EEPROM、Flash ROM的区别

Linux下Fork与Exec使用

http://www.cnblogs.com/hicjiajia/archive/2011/01/20/1940154.html

 

ARM Linux启动过程分析

http://www.go-gddq.com/html/QianRuShiXiTong-JiShu/2012-08/1042290p2.htm

 

Android arm
linux kernel
启动流程

http://blog.csdn.net/yili_xie/article/details/5716837

 

Androidinit过程详解(一)

http://www.cnblogs.com/nokiaguy/archive/2013/04/14/3020774.html

 

Androidinit过程(二):初始化语言(init.rc)解析

http://www.cnblogs.com/nokiaguy/p/3164799.html

转 android launch flow的更多相关文章

  1. Launch iCar Scan Android Scanner Support Bluetooth X431 iDiag Update Version

    Autonumen.com release new Launch iCar Scan for Android,Launch iCarScan Bluetooth Scanner is update v ...

  2. [Kotlin Tutorials 19] Kotlin Flows, SharedFlow and StateFlow in Android

    Kotlin Flows 本文包含的内容: Flow是什么, 基本概念和用法. Flow的不同类型, StateFlow和SharedFlow比较. Flow在Android中的使用 安全收集. 操作 ...

  3. [Android] Visual Studio Emulator For Android 相关

    1.修改设备名 C:\Users\[用户名]\AppData\Local\Microsoft\VisualStudioEmulator\Android\Containers\Local\Devices ...

  4. Android本地数据存储之SQLite关系型数据库 ——SQLiteDatabase

    数据库的创建,获取,执行sql语句: 框架搭建:dao 思考: 1.数据库保存在哪里? 2.如何创建数据库?如何创建表? 3.如何更新数据库?如何更改表的列数据? 4.如何获取数据库? 5.如何修改数 ...

  5. android 运行时出现The connection to adb is down, and a severe error has occured.(转)

    点击项目run,报了这样的错,前几天都好好的:   [2013-09-14 15:27:13 - QualityPicture_Client1.3.1.9.7.1] ----------------- ...

  6. vs emulator for android使用

    在windows上调试android程序,可以利用hyperv虚拟化功能,微软也提供了模拟工具和android studio.eclipse的配置说明,不再累述. 关于启动vs模拟器的cmd命令: e ...

  7. android 之 adb 启动问题的一般解决办法

    有时,当我们打开eclipse准备运行Android项目时,虚拟机会启动不了,并且会出现下面的报错. [2015-10-07 16:47:46 - Game2048] ---------------- ...

  8. Android虚拟机常见错误及解决办法

    第一个: [2012-11-09 13:15:14 - Tesa] Android Launch! [2012-11-09 13:15:14 - Tesa] The connection to adb ...

  9. Android:单元测试Junit的配置

    在实际开发中,开发android软件的过程需要不断地进行测试.而使用Junit测试框架,侧是正规Android开发的必用技术,在Junit中可以得到组件,可以模拟发送事件和检测程序处理的正确性.... ...

随机推荐

  1. 受限玻尔兹曼机(RBM)学习笔记(一)预备知识

    去年 6 月份写的博文<Yusuke Sugomori 的 C 语言 Deep Learning 程序解读>是囫囵吞枣地读完一个关于 DBN 算法的开源代码后的笔记,当时对其中涉及的算法原 ...

  2. 基于Redis的BloomFilter算法去重

    BloomFilter算法及其适用场景 BloomFilter是利用类似位图或者位集合数据结构来存储数据,利用位数组来简洁的表示一个集合,并且能够快速的判断一个元素是不是已经存在于这个集合.因为基于H ...

  3. css中px,em和rem的区别

    css中px,em和rem的区别 今天,突然间发现一个特别有意思的问题,就是无意间看到一个网站中的em并不是16px,下面展开了对于px和em以及rem的探究. 首先,px是绝对长度单位,是相对于显示 ...

  4. 当我们安装使用时,会出现eclipse启动不了,出现“Java was started but returned exit code=13......”的问题

    安装win8.1后,启动eclipse,也会提示 "java was started but returned exit code=13" 可能是eclipse.ini配置文件错误 ...

  5. ADO.NET学习系列(一)

    一.ADO.NET基础 程序和数据库交互,要通过ADO.NET进行:通过ADO.NET就能在数据库中执行SQL了.ADO.NET中提供了对不同数据库的统一操作接口(ODBC).另外还有一种操作数据库的 ...

  6. BI之SSAS完整实战教程5 -- 详解多维数据集结构

    之前简单介绍过多维数据集(Cube)的结构. 原来计划将Cube结构这部分内容打散,在实验中穿插讲解, 考虑到结构之间不同的部分都有联系,如果打散了将反而不好理解,还是直接一次性全部讲完. 本篇我们将 ...

  7. Hibernate框架之关联映射入门

    关联映射就是将关联关系映射到数据库里,在对象模型中就是一个或多个引用. 一:配置单向多对一关联 在Emp类中定义一个Dept属性,而在Dept类中无须定义用于存放Emp对象的集合属性 01.Dept. ...

  8. 从" ThinkPHP 开发规范 "看 PHP 的命名规范和开发建议

    稍稍水一篇博客,摘抄自Think PHP 的开发规范,很有引导性,我们可以将这些规范实践到原生 PHP 中. 命名规范 使用ThinkPHP开发的过程中应该尽量遵循下列命名规范: 类文件都是以.cla ...

  9. 桂电在linux、Mac OS环境下使用出校器(支持2.14)

    这是guetsec学长在三院科协学长所抓包逆向分析1.81版出校器的基础上,用python写的一款为Mac和linux环境开发的出校器. 最后我做了略微修改,支持暂时最新版本2.14.下面有直接从源码 ...

  10. HTML 块元素

    分为3类 1. 结构块 只能包含块级元素.它们包含结构含义,但没有语义含义,也就是,不能说明内容是什么,只能说明其组织方式. <ol> <ul> <dl> < ...