android开机启动过程
Android系统开机主要经历三个阶段:
- bootloader启动
- Linux启动
- 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件事情:
- Zygote注册一个socket用了进行进程通信,当我们需要启动一个Android应用程序时,AMS会通过Socket通知Zygote为这个应用程序创建一个新的进程。
- Zygote进程fork出一个SystemServer进程,SystemServer进程负责启动系统的关键服务,如包管理服务PackageManagerService和应用程序组件管理服务ActivityManagerService。具体运行过程见f
- 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系统启动过程全部完成
android开机启动过程的更多相关文章
- ANDROID 开机启动VNC SERVER
ANDROID 开机启动VNC SERVER 背景信息: 最近在做一个项目,在项目需求中有这么一项“要把VNC SERVER 添加到android里并让其开机自启动”.其实做这个项目也挺缚手缚脚的,因 ...
- Android程序启动过程深入解析
当按下Android设备电源键时究竟发生了什么? Android的启动过程是怎么样的? 什么是Linux内核? 桌面系统linux内核与Android系统linux内核有什么区别? 什么是引导装载程序 ...
- android开机启动流程说明
android开机启动流程说明 第一步:启动linux 1.Bootloader 2.Kernel 第二步android系统启动:入口为init.rc(system\core\rootdir) 1./ ...
- Android开机启动Activity或者Service方法
本文出自 “Bill_Hoo专栏” 博客,请务必保留此出处http://billhoo.blog.51cto.com/2337751/761230 这段时间在做Android的基础开发,现在有一需求是 ...
- LINUX开机启动过程
LINUX开机启动过程 启动第一步--加载BIOS当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它.这是因为BIOS中包含了CPU的相关信息 ...
- Android开机启动Activity或者Service方法(转载)
这段时间在做Android的基础开发,现在有一需求是开机启动,按照网上某些博文教程做了下,始终不成功,一开机总是提示所启动的应用程序意外终止,于是参考了Android SDK doc,终于解决问题,下 ...
- Linux入门——开机启动过程浅析
Linux开机启动过程浅析 Introduction 开机启动过程分为以下6个步骤,分别是BIOS, MBR, GRUB, Kernel, Init, RunLevel, RunDefinition ...
- Zygote和System进程的启动过程、Android应用进程启动过程
1.基本过程 init脚本的启动Zygote Zygote进程的启动 System进程的启动 Android应用进程启动过程 2.init脚本的启动 +------------+ +-------+ ...
- Android开机启动程序
android程序实现开机启动的原理,简单点说就是做一个广播接收器,接收到开机广播时就启动activity或service或执行其它操作.Android系统在启动的时候会发出一个开机广播,内容为ACT ...
随机推荐
- 慢慢聊Linux AIO
一.What:异步IO是什么? 1. 一句话总结 允许进程发起很多I/O操作,而不用阻塞或等待任何操作完成 2. 详细说说 一般来说,服务器端的I/O主要有两种情况:一是来自网络的I/O:二是对文件 ...
- Hbase之插入数据
/** * Created by similarface on 16/8/17. */ import org.apache.hadoop.conf.Configuration; import org. ...
- springside3.1.8打包
地址寻找 https://sourceforge.net/ https://sourceforge.net/projects/springside/files/SpringSide%203.0/3.3 ...
- Spring Boot 学习
下载安装了如下软件.设置了环境变量. Groovy-Groovy是一种基于JVM(Java虚拟机)的敏捷开发语言,它结合了Python.Ruby和Smalltalk的许多强大的特性,Groovy 代码 ...
- GRUB4DOS入门
目 录 第1章 GRUB4DOS入门 1 1.1 用途 1 1.2 安装 1 1.2.1 修改MBR 1 1.2.2 修改PBR 3 1.2.3 DOS 4 1.2 ...
- 使用TCP/IP的套接字(Socket)进行通信
http://www.cnblogs.com/mengdd/archive/2013/03/10/2952616.html 使用TCP/IP的套接字(Socket)进行通信 套接字Socket的引入 ...
- 本地化Model Factory
即让其生成中文的测试数据 先简单介绍Model Factory两个常用方法: 进入tinker页面生成测试数据: Factory(User::class,10)->make():make()方法 ...
- 九度 题目1437:To Fill or Not to Fill
题目描述: With highways available, driving a car from Hangzhou to any other city is easy. But since the ...
- Java文件编码格式转换
转自博文<Java文件编码格式转换>: 默认被转换的格式为GBK,转换成的格式为UTF-8 import info.monitorenter.cpdetector.CharsetPrint ...
- 数组作为hash元素的时候如何push
####################################################################### # Copyright (C) 2015 All rig ...