当我们按下电源键,Android 究竟做了些什么?
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~
相信我们对Android系统都不陌生,而Android系统博大精深,被各种各样的智能设备承载的同时,我们会否好奇过,如此复杂的Android究竟是怎么运作起来的呢?借本文给大家分享,笔者对Android 系统启动流程的整体理解~
hi, I'm Android
现在,按下电源键
下面是Android启动的核心步骤流程图,看文字的时候,记得回来对照图来理解喔,希望阅读全文后,回观流程图,会有恍然大悟的感觉,那么文章的目的就达到啦~
整体流程
一、启动电源及系统启动
系统从 ROM 中开始启动,加载引导程序到 RAM ,然后执行。
二、引导程序
引导程序是 Android 操作系统开始运行前的一个小程序,因此它需要针对特定主板与芯片,并不是 Android 操作系统的一部分。引导程序是 OEM 厂商或运行商进行加锁、限制的地方。
1 两个阶段
- 检测外部 RAM 以及为第二阶段加载程序
- 设置网络、内存等,搭建内核运行环境(为了达到特殊目的时,引导程序可以根据配置参数或者输入数据来设置内核)
2 引导程序的加载器
Android引导程序可以在\bootable\bootloader\legacy\usbloader找到,传统的加载器包含的两个文件:
- init.s 初始化堆栈,清零BSS段,会调用 main.c 中的 _main()函数 (bss segment:通常是指用来存放程序中未初始化的全局变量的一块内存区域;BSS - Block Started by Symbol。BSS段属于静态内存分配)
- main.c 初始化硬件,创建 linux 标签
三、内核启动
Android 内核启动方式类似桌面 linux,主要步骤:
1. 设置缓存
2. 被保护存储器
3. 计划列表
4. 加载驱动
当内核完成系统设置,接下来即将启动系统的第一个进程 -- init 进程
四、init 进程
作为 Android 系统的第一个进程,其PID为0,通过解析 init.rc 脚本来构建出系统初始运行形态,这一阶段中,“Android” logo 会显示出来
(系统中,大多数系统服务程序都是在该脚本中描述并被相继启动的)
init.rc 由4种类型声明组成:Actions、Commands、Services、Options
- Actions:响应某事件的过程。当“trigger”所描述的触发事件产生时,则依次执行各种“command” 源码角度:系统会对 init.rc 中各“trigger”进行匹配,当发现符合条件的 Action,就将它加入“命令执行队列”尾部(除非 Action 已存在队列中),然后系统再对这些命令按顺序进行。on ##触发条件 ##执行命令 ##可执行多个命令 ...
- Commands:命令将在所属事件发生时被一个个执行
- Services:可执行程序,它们在特定选项的约束下会被 init 程序运行或者重启(Service 可以在配置中指定是否需要退出重启,那么,当 Service 出现异常 crash 时,可有机会复原)service []*
- Options:对 service 的约束选项
五和六、 ServiceManager、Zygote、SystemServer
科普:Daemons - 守护进程
init进程通过解析 init.rc 来陆续启动其他关键的系统服务进程,其中最重要的是 ServiceManager、Zygote 和 SystemServer 三者,下面我们逐一解析:
1 ServiceManager -- Binder 机制支撑者
概述:ServiceManager 是 Binder 机制中的支撑者,负责某 Binder 服务注册信息到底层 Binder 驱动分配的值解析。
ServiceManager 由 init 进程解析 rc 脚本时启动,属于 core 类,其他同类进程包括:uenetd、console、adbd等。根据 core 组的特性,这些进程会同时启动或停止。另外,ServiceManager 配置含有 critical 属性,这意味着它是系统关键进程(如果进程不幸在4分钟内异常退出超过4次,设备将重启并进入还原模式)。当 ServiceManager 每次重启时,其他关键进程:zygote、media、surfaceflinger 等也会被 restart。
2. Zygote -- “孕育”新线程与进程
Android 中大多数应用进程与系统进程都是通过 Zygote 来生成的。Zygote 同样由 init 解析 rc 脚本时启动,属于 main 类,同属 main 类的系统进程有:netd、debuggerd、rild等。Zygote并不是处于独立的程序中的,它所在程序名为“app_process”,观察 app_process 主函数实现知道,如果 init.rc 中指定了 --zygote选项,app_process 接下来将启动“ZygoteInit”,并传入“start-system-server”,这样,ZygoteInit 就会运行在虚拟机上(Dalvik VM)上了。
ZygoteInit 函数有两项重要工作
预装载各种系统类
搭建 SystemServer 环境,并启动 SystemServer(大部分的 Android 系统服务都在其中,由 Java 编写)
ZygoteInit 流程总结
(
摘自:Gityuan -- Android 系统启动-Zygote 篇
)
- 解析init.zygote.rc中的参数,创建AppRuntime并调用AppRuntime.start()方法;
- 调用AndroidRuntime的startVM()方法创建虚拟机,再调用startReg()注册JNI函数;
- 通过JNI方式调用ZygoteInit.main(),第一次进入Java世界;
- registerZygoteSocket()建立socket通道,zygote作为通信的服务端,用于响应客户端请求;
- preload()预加载通用类、drawable和color资源、openGL以及共享库以及WebView,用于提高ap启动效率;
- zygote完毕大部分工作,接下来再通过startSystemServer(),fork得力帮手system_server进程,也是上层framework的运行载体。
- zygote功成身退,调用runSelectLoop(),随时待命,当接收到请求创建新进程请求时立即唤醒并执行相应工作。
ZygoteInit 结束后,开机Logo就出来了。
(注意:这里并不包括开机动画,而是开机前 “Android” Logo 出现的那个画面,开机动画出现之前还需要进行各种加载,开机动画是在“Android” Logo 出现之后才播放的)
3. SystemServer -- 大部分 Android 系统服务所在地
SystemServer 是 Android 进入 Launcher 前的最后准备,它提供了众多的由“Java”语言编写的系统服务。
如果 init.rc 中为 zygote 指定启动参数 --start-system-server,那么 ZygotyeInit 就会调用 startSystemServer 来进入 SystemServer。
- startSystemServer函数解析:
- 首先 ZygoteInit 通过 Zygote.forkSystemServer 来生成一个新的线程(fork),用于承载各种系统服务。(源码角度:Zygote 内部由 Native 函数 Dalvik_dalvik_system_Zygote_forkSystemServer 来进一步实现,最终调用底层接口的 fork 接口来实际产生进程)
- 根据fork特性,子进程与父进程将获得相同的代码环境。pid为0为子进程,否则为父进程;如果是前者,则进一步调用 handleSystemServerProcess(parseArgs) 函数来完成最核心的工作 -- “启动各系统服务”(源码角度:handleSystemServerProcess 方法将 startSystemServer 中的 parsedArgs.remainingArgs 参数传给 RuntimeInit.zygoteInit,后者又调用 nativeZygoteInit 函数)
- nativeZygoteInit 调用后,接着,三个重要的 static 函数就要被执行了:init1 - 完成本地Service(SurfaceFlinger、AudioFlinger等)启动,完成后调用 init2、init2 - 新建一个新的带 Looper 的线程 ServerThread来启动 Java层各 Service
后语
上面对 Android 系统启动做了一个简述,意在给大家展现一个整体流程,其中每个环节涉及的知识点只是浅浅掠过,笔者也尚在学习与探索中,希望在后续再作详细分析。
资源推荐
- Gityuan - Android 开篇
- 老罗的Android之旅
- 《深入理解 Android 内核设计思想》 由浅入深,落实到源码层面上进行探索,知识很有深度
此文已由作者授权腾讯云+社区发布,更多原文请点击
搜索关注公众号「云加社区」,第一时间获取技术干货,关注后回复1024 送你一份技术课程大礼包!
海量技术实践经验,尽在云加社区!
当我们按下电源键,Android 究竟做了些什么?的更多相关文章
- 按下开机键,Linux做了什么?
作者:Vamei 来源:见文末 计算机开机是一个神秘的过程.我们只是按了开机键,就看到屏幕上的进度条或者一行行的输出,直到我们到达登录界面.然而,计算机开机又是个异常脆弱的过程,我们满心期望的登录界面 ...
- 为什么 java wait/notify 必须与 synchronized 一起使用,jvm究竟做了些什么
这个课题提出来的是原先的线程并发解决的思路.目前解决线程并发,可以是lock接口结合condition 并发问题一直以来就是线程必不可少的话题. java 是第一个内置对多线程支持的主流编程语言.在 ...
- 【Android测试】【随笔】模拟长按电源键
◆版权声明:本文出自胖喵~的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/5195121.html 起因 昨天群里看到有人问如何实现一个 ...
- Android 按下电源按钮关闭小学习过程的整个长度
Android 按下电源按钮关闭小学习过程的整个长度 近期研究了一下android关机跟又一次启动功能,看了一些长按电源键到弹出关机对话框,到真正关机的一系列处理过程. 首先还是来看看这个长按电源键都 ...
- Android-服务中监听电源键和Home键的广播、在锁屏下仍然工作的方法
Android-服务中监听电源键和Home键的广播 http://blog.csdn.net/u014657752/article/details/49512485 Android开发之如何监听让服 ...
- 【转】Android 音量键+电源键 截屏代码小结
http://104zz.iteye.com/blog/1752961 原文地址:http://blog.csdn.net/hk_256/article/details/7306590 ,转载请注明出 ...
- android中按电源键锁屏然后解锁导致Activity调用onDestory以及如何防止锁屏
今天在android项目中按电源键锁屏,然后解锁,发现子Activity关闭了,回到了主页,这个问题困扰了我很久,最后打log发现,在按电源键的时候,调用了子Activity的onDestroy()方 ...
- Android 应用按两下返回键退出应用程序
在android应用开发中,有时候应用会用到按两下返回键退出应用的功能,今天介绍一下这个功能,直接上代码: @Override public boolean dispatchKeyEvent(KeyE ...
- Android按下home键后重新打开app进入主activity的问题
问题阐述: 当我们写一款App的时候,势必会有这种情况:用户已经进行了多级的操作,现返回栈中已存在多个activity,那么这个时候我们想回到最初的activity难道要一层层的返回吗,对用户来说 无 ...
随机推荐
- 大数据核心知识点:Hbase、Spark、Hive、MapReduce概念理解,特点及机制
今天,上海尚学堂大数据培训班毕业的一位学生去参加易普软件公司面试,应聘的职位是大数据开发.面试官问了他10个问题,主要集中在Hbase.Spark.Hive和MapReduce上,基础概念.特点.应用 ...
- 如何理解Python装饰器
如何理解Python装饰器?很多学员对此都有疑问,那么上海尚学堂python培训这篇文章就给予答复. 一.预备知识 首先要理解装饰器,首先要先理解在 Python 中很重要的一个概念就是:“函数是 F ...
- Java Web每天学之Servlet的原理解析
Java Web每天学之Servlet的工作原理解析,上海尚学堂Java技术文章Java Web系列之二上一篇文章Java Web每天学之Servlet的工作原理解析是之一,欢迎点击阅读. Servl ...
- C 基于数组存储的堆栈实现
一.堆栈简介 对于需要管理的队列,主要操作是在序列的末尾插入和取出(删除)元素,有这样操作要求的序列我们称之为堆栈(Stack). 堆栈可以认为是具有一定约束的线性表,插入和删除都作用在一个称为栈顶( ...
- [Swift]LeetCode33. 搜索旋转排序数组 | Search in Rotated Sorted Array
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...
- [Swift]LeetCode373. 查找和最小的K对数字 | Find K Pairs with Smallest Sums
You are given two integer arrays nums1 and nums2 sorted in ascending order and an integer k. Define ...
- [Swift]LeetCode493. 翻转对 | Reverse Pairs
Given an array nums, we call (i, j) an important reverse pair if i < j and nums[i] > 2*nums[j] ...
- 记录一次安装OpenGL的漫长过程
尝试codeblock和Dev-C++ 这学期新开了一门计算机图形图像的课,里面涉及到openGL,中午跑到图书馆开始倒腾OpenGL. 因为电脑里本来有codeblock,于是就想不用教材里面所说的 ...
- java基础(十四)-----详解匿名内部类——Java高级开发必须懂的
在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意的事项.匿名内部类使用的形参为何要为final. 使用匿名内部类内部类 匿名内部类由于没有名字,所以它的创建方式有点儿奇怪.创建格式如下: n ...
- 《你必须知道的.NET》读书实践:一个基于OO的万能加载器的实现
此篇已收录至<你必须知道的.Net>读书笔记目录贴,点击访问该目录可以获取更多内容. 一.关于万能加载器 简而言之,就是孝顺的小王想开发一个万能程序,可以一键式打开常见的计算机资料,例如: ...