【转】Android系统开篇
版权声明:本站所有博文内容均为原创,转载请务必注明作者与原文链接,且不得篡改原文内容。另外,未经授权文章不得用于任何商业目的。
一、引言
Android系统非常庞大、错综复杂,其底层是采用Linux作为基底,上层采用包含虚拟机的Java层以及Native层,通过系统调用(Syscall)连通系统的内核空间与用户空间。用户空间主要采用C++和Java代码,通过JNI技术打通用户空间的Java层和Native层(C++/C),从而融为一体。
Google官方提供了一张经典的四层架构图,从下往上依次分为Linux内核、系统库和Android运行时环境、框架层以及应用层这4层架构,其中每一层都包含大量的子模块或子系统。这只是如垒砖般地分层,并没有表达Android整个系统的内部架构、运行机理,以及各个模块之间是如何衔接与配合工作的。为了更深入地掌握Android整个架构思想以及各个模块在Android系统所处的地位与价值,计划以Android系统启动过程为主线,以进程的视角来诠释Android M系统全貌,全方位的深度剖析各个模块功能,争取各个击破。这样才能犹如庖丁解牛,解决、分析问题则能游刃有余。
二、Android架构
Google提供的4层架构图很经典,但为了更进一步透视Android系统架构,本文更多的是以进程的视角,以分层的架构来诠释Android系统的全貌,阐述Android内部的环环相扣的内在联系。
系统启动架构图
点击查看大图
图解: Android系统启动过程由上图从下往上的一个过程:Loader
-> Kernel
-> Native
-> Framework
-> App
,接来下简要说说每个过程:
2.1 Loader层
- Boot ROM: 当手机处于关机状态时,长按Power键开机,引导芯片开始从固化在
ROM
里的预设出代码开始执行,然后加载引导程序到RAM
; - Boot Loader:这是启动Android系统之前的引导程序,主要是检查RAM,初始化硬件参数等功能。
2.2 Kernel层
Kernel层是指Android内核层,到这里才刚刚开始进入Android系统。
- 启动Kernel的swapper进程(pid=0):该进程又称为idle进程, 系统初始化过程Kernel由无到有开创的第一个进程, 用于初始化进程管理、内存管理,加载Display,Camera Driver,Binder Driver等相关工作;
- 启动kthreadd进程(pid=2):是Linux系统的内核进程,会创建内核工作线程kworkder,软中断线程ksoftirqd,thermal等内核守护进程。
kthreadd进程是所有内核进程的鼻祖
。
2.3 Native层
这里的Native层主要包括init孵化来的用户空间的守护进程、HAL层以及开机动画等。启动init进程(pid=1),是Linux系统的用户进程,init进程是所有用户进程的鼻祖
。
- init进程会孵化出ueventd、logd、healthd、installd、adbd、lmkd等用户守护进程;
- init进程还启动
servicemanager
(binder服务管家)、bootanim
(开机动画)等重要服务 - init进程孵化出Zygote进程,Zygote进程是Android系统的第一个Java进程(即虚拟机进程),
Zygote是所有Java进程的父进程
,Zygote进程本身是由init进程孵化而来的。
2.4 Framework层
- Zygote进程,是由init进程通过解析init.rc文件后fork生成的,Zygote进程主要包含:
- 加载ZygoteInit类,注册Zygote Socket服务端套接字;
- 加载虚拟机;
- preloadClasses;
- preloadResouces。
- System Server进程,是由Zygote进程fork而来,
System Server是Zygote孵化的第一个进程
,System Server负责启动和管理整个Java framework,包含ActivityManager,PowerManager等服务。 - Media Server进程,是由init进程fork而来,负责启动和管理整个C++ framework,包含AudioFlinger,Camera Service,等服务。
2.5 App层
- Zygote进程孵化出的第一个App进程是Launcher,这是用户看到的桌面App;
- Zygote进程还会创建Browser,Phone,Email等App进程,每个App至少运行在一个进程上。
- 所有的App进程都是由Zygote进程fork生成的。
2.6 Syscall && JNI
- Native与Kernel之间有一层系统调用(SysCall)层,见Linux系统调用(Syscall)原理;
- Java层与Native(C/C++)层之间的纽带JNI,见Android JNI原理分析。
三、通信方式
无论是Android系统,还是各种Linux衍生系统,各个组件、模块往往运行在各种不同的进程和线程内,这里就必然涉及进程/线程之间的通信。对于IPC(Inter-Process Communication, 进程间通信),Linux现有管道、消息队列、共享内存、套接字、信号量、信号这些IPC机制,Android额外还有Binder IPC机制,Android OS中的Zygote进程的IPC采用的是Socket机制,在上层system server、media server以及上层App之间更多的是采用Binder IPC方式来完成跨进程间的通信。对于Android上层架构中,很多时候是在同一个进程的线程之间需要相互通信,例如同一个进程的主线程与工作线程之间的通信,往往采用的Handler消息机制。
想深入理解Android内核层架构,必须先深入理解Linux现有的IPC机制;对于Android上层架构,则最常用的通信方式是Binder、Socket、Handler,当然也有少量其他的IPC方式,比如杀进程Process.killProcess()采用的是signal方式。下面说说Binder、Socket、Handler:
3.1 Binder
Binder作为Android系统提供的一种IPC机制,无论从系统开发还是应用开发,都是Android系统中最重要的组成,也是最难理解的一块知识点,想了解为什么Android要采用Binder作为IPC机制? 可查看我在知乎上的回答。深入了解Binder机制,最好的方法便是阅读源码,借用Linux鼻祖Linus Torvalds曾说过的一句话:Read The Fucking Source Code。下面简要说说Binder IPC原理。
Binder IPC原理
Binder通信采用c/s架构,从组件视角来说,包含Client、Server、ServiceManager以及binder驱动,其中ServiceManager用于管理系统中的各种服务。
- 想进一步了解Binder,可查看Binder系列—开篇,Binder系列花费了13篇文章的篇幅,从源码角度出发来,讲述Driver、Native、Framework、App四个层面的整个完整流程。根据有些读者反馈这个系列还是不好理解,这个binder涉及的层次跨度比较大,知识量比较广, 建议大家先知道binder是用于进程间通信,有个大致概念就可以.先去学习系统基本知识,等后面有一定功力再进一步深入研究Binder.
原理篇
序号 | 文章名 | 概述 |
---|---|---|
0 | Binder系列—开篇 | Binder概述 |
1 | Binder系列3—启动Service Manager | ServiceManager守护进程 注册和查询服务 |
2 | Binder系列4—获取Service Manager | 获取代理对象BpServiceManager |
3 | Binder系列5—注册服务(addService) | 注册Media服务 |
4 | Binder系列6—获取服务(getService) | 获取Media代理,以及DeathRecipient |
5 | Binder系列7—framework层分析 | framework层服务注册和查询,Binder注册 |
6 | 理解Binder线程池的管理 | Binder的startThreadPool过程 |
7 | 彻底理解Android Binder通信架构 | startService为主线 |
8 | Binder系列10—总结 | Binder的简单总结 |
9 | Binder IPC的权限控制 | clearCallingIdentity/restoreCallingIdentity |
10 | Binder死亡通知机制之linkToDeath | Binder死亡通知机制 |
驱动篇:
1 | Binder系列1—Binder Driver初探 | 驱动open/mmap/ioctl,以及binder结构体 |
2 | Binder系列2—Binder Driver再探 | Binder通信协议,内存机制 |
使用篇:
1 | Binder系列8—如何使用Binder | Native层、Framwrok层自定义Binder服务 |
2 | Binder系列9—如何使用AIDL | App层自定义Binder服务 |
3.2 Socket
Socket通信方式也是C/S架构,比Binder简单很多。在Android系统中采用Socket通信方式的主要:
- zygote:用于孵化进程,系统进程system_server孵化进程时便通过socket向zygote进程发起请求;
- installd:用于安装App的守护进程,上层PackageManagerService很多实现最终都是交给它来完成;
- lmkd:lowmemorykiller的守护进程,Java层的LowMemoryKiller最终都是由lmkd来完成;
- adbd:这个也不用说,用于服务adb;
- logcatd:这个不用说,用于服务logcat;
- vold:即volume Daemon,是存储类的守护进程,用于负责如USB、Sdcard等存储设备的事件处理。
等等还有很多,这里不一一列举,Socket方式更多的用于Android framework层与native层之间的通信。Socket通信方式相对于binder非常简单,所以一直没有写相关文章,为了成一个体系,下次再补上。
3.3 Handler
Binder/Socket用于进程间通信,而Handler消息机制用于同进程的线程间通信,Handler消息机制是由一组MessageQueue、Message、Looper、Handler共同组成的,为了方便且称之为Handler消息机制。
有人可能会疑惑,为何Binder/Socket用于进程间通信,能否用于线程间通信呢?答案是肯定,对于两个具有独立地址空间的进程通信都可以,当然也能用于共享内存空间的两个线程间通信,这就好比杀鸡用牛刀。接着可能还有人会疑惑,那handler消息机制能否用于进程间通信?答案是不能,Handler只能用于共享内存地址空间的两个线程间通信,即同进程的两个线程间通信。很多时候,Handler是工作线程向UI主线程发送消息,即App应用中只有主线程能更新UI,其他工作线程往往是完成相应工作后,通过Handler告知主线程需要做出相应地UI更新操作,Handler分发相应的消息给UI主线程去完成,如下图:
由于工作线程与主线程共享地址空间,即Handler实例对象mHandler
位于线程间共享的内存堆上,工作线程与主线程都能直接使用该对象,只需要注意多线程的同步问题。工作线程通过mHandler
向其成员变量MessageQueue
中添加新Message,主线程一直处于loop()方法内,当收到新的Message时按照一定规则分发给相应的handleMessage
()方法来处理。所以说,而Handler消息机制用于同进程的线程间通信的核心是线程间共享内存空间,而不同进程拥有不同的地址空间,也就不能用handler来实现进程间通信。
上图只是Handler消息机制的一种处理流程,是不是只能工作线程向UI主线程发消息呢,其实不然,可以是UI线程向工作线程发送消息,也可以是多个工作线程之间通过handler发送消息。更多关于Handler消息机制文章:
要理解framework层源码,掌握这3种基本的进程/线程间通信方式是非常有必要,当然Linux还有不少其他的IPC机制,比如共享内存、信号、信号量,在源码中也有体现,如果想全面彻底地掌握Android系统,还是需要对每一种IPCd机制都有所了解。
四、核心提纲
2016年新的一年刚开始,首先祝大家、也祝自己在新的一年诸事顺心,事业蒸蒸日上。在过去的一年,对于Android从底层一路到上层有不少自己的理解和沉淀,但总体较零散,未成体系。借着今天(元旦假日的最后一天),给自己的新的一年提前做一个计划,把知识进行归档整理与再学习,从而加深对Android架构的理解。通过前面对系统启动的介绍,相信大家对Android系统有了一个整体观,接下来需要抓核心、理思路,争取各个击破。
计划:不少文章还没来得及进一步加工,大篇章的源码,有读者跟我反馈看着发困,先别急,文章还会不断更新和升级。前期计划先将系统所有核心技术点的边整理边写博客; 后期工作有时间再根据大家的反馈以及自己的校验,再不断修正和完善所有文章,争取给文章,再进一步精简非核心代码,增加可视化图表以及文字的结论性分析。
博客定位: 基于Android 6.0的源码
,专注于分享Android系统原理、架构分析的原创文章。
建议阅读群体: 适合于正从事或者有兴趣研究Android系统的工程师或者爱好者,也适合Android app高级工程师; 对于尚未入门或者刚入门的app程序员阅读可能会困难些,可能不是很适合。
看到Android整个系统架构是如此庞大的, 该问如何学习Android系统, 以下是我自己琢磨的Android的学习和研究论,仅供参考:如何自学Android.
4.1 系统启动系列
Android系统启动-概述: Android系统中极其重要进程:init, zygote, system_server, servicemanager 进程:
序号 | 进程启动 | 概述 |
1 | init进程 | Linux系统中用户空间的第一个进程, Init.main |
2 | zygote进程 | 所有App进程的父进程, ZygoteInit.main |
3 | system_server进程(上篇) | 系统各大服务的载体, forkSystemServer过程 |
4 | system_server进程(下篇) | 系统各大服务的载体, SystemServer.main |
5 | servicemanager进程 | binder服务的大管家, 守护进程循环运行在binder_loop |
6 | app进程 | 通过Process.start启动App进程, ActivityThread.main |
再来看看守护进程(进程名一般以d为后缀,比如logd), 先介绍以下部分,后缀再增加.
4.2 系统稳定性系列
Android系稳定性主要是异常崩溃(crash)和执行超时(timeout), Android系统稳定性简述 :
序号 | 文章名 | 概述 |
1 | 理解Android ANR的触发原理 | 触发ANR的场景以及机理 |
2 | Input系统—ANR原理分析 | input触发ANR的原理 |
3 | 理解Android ANR的信息收集过程 | AMS.appNotResponding过程分析,收集traces |
4 | ART虚拟机之Trace原理 | kill -3 信息收集过程 |
5 | Native进程之Trace原理 | debuggerd -b 信息收集过程 |
6 | WatchDog工作原理 | WatchDog触发机制 |
7 | 理解Java Crash处理流程 | AMS.handleApplicationCrash过程分析 |
8 | 理解Native Crash处理流程 | debuggerd守护进程 |
4.3 Android进程系列
进程对于系统非常重要,系统运转,各种服务、组件的载体都依托于进程,对进程理解越深刻,越能掌握系统整体架构。那么先来看看进程相关:
序号 | 文章名 | 概述 |
1 | 理解Android进程创建流程 | Process.start过程分析 |
2 | 理解杀进程的实现原理 | Process.killProcess过程分析 |
3 | Android四大组件与进程启动的关系 | AMS.startProcessLocked过程分析组件与进程 |
4 | Android进程绝杀技–forceStop | force-stop过程分析彻底移除组件与杀进程 |
5 | 理解Android线程创建流程 | 3种不同线程的创建过程 |
6 | 彻底理解Android Binder通信架构 | 以start-service为线,阐述进程间通信机理 |
7 | 理解Binder线程池的管理 | Zygote fork的进程都默认开启binder线程池 |
8 | Android进程生命周期与ADJ | 进程adj, processState以及lmk |
9 | Android LowMemoryKiller原理分析 | lmk原理分析 |
10 | 进程优先级 | 进程nice,thread priority以及scheduler |
11 | Android进程调度之adj算法 | updateOomAdjLocked过程 |
12 | Android进程整理 | 整理系统的所有进程/线程 |
4.4 四大组件系列
对于App来说,Android应用的四大组件Activity,Service,Broadcast Receiver, Content Provider最为核心,接下分别展开介绍:
序号 | 文章名 | 类别 |
1 | startActivity启动过程分析 | Activity |
2 | 简述Activity生命周期 | Activity |
3 | startService启动过程分析 | Service |
4 | bindService启动过程分析 | Service |
5 | 以Binder视角来看Service启动 | Service |
6 | Android Broadcast广播机制分析 | Broadcast |
7 | 理解ContentProvider原理 | ContentProvider |
8 | ContentProvider引用计数 | ContentProvider |
9 | Activity与Service生命周期 | Activity&&Service |
10 | 简述Activity与Window关系 | Activity&&Window |
11 | 四大组件之综述 | AMS |
12 | 四大组件之ServiceRecord | Service |
13 | 四大组件之BroadcastRecord | Broadcast |
14 | 四大组件之ContentProviderRecord | ContentProvider |
15 | 理解Android Context | Context |
16 | 理解Application创建过程 | Application |
17 | unbindService流程分析 | Service |
18 | 四大组件之ActivityRecord | Activity |
19 | AMS总结(一) | AMS |
4.5 图形系统系列
图形也是整个系统非常复杂且重要的一个系列,涉及WindowManager,SurfaceFlinger.
序号 | 文章名 | 类别 |
1 | WindowManager启动篇 | Window |
2 | WMS之启动窗口篇 | Window |
3 | 以Window视角来看startActivity | Window |
4 | Android图形系统概述 | SurfaceFlinger |
5 | SurfaceFlinger启动篇 | SurfaceFlinger |
6 | SurfaceFlinger绘图篇 | SurfaceFlinger |
7 | Choreographer原理 | Choreographer |
4.6 系统服务篇
再则就是在整个架构中有大量的服务,都是基于Binder来交互的,计划针对部分核心服务来重点分析:
系统服务的注册过程, 见Android系统服务的注册方式
- AMS服务
- AMS启动过程(一)
- 更多组件篇[见小节4.3]
- Input系统
- PKMS服务
- Alarm服务
- JobScheduler服务
- BatteryService
- PMS服务
- DropBox服务
- UserManagerService
- 更多服务介绍, 敬请期待…
4.7 内存&&存储篇
- 内存篇
- 存储篇
- Linux驱动篇
- 敬请期待
- dalvik/art
4.8 工具篇
最后,说说Android相关的一些常用命令和工具以及调试手段.
序号 | 文章名 | 类别 |
1 | 理解Android编译命令 | build |
2 | 性能工具Systrace | systrace |
3 | Android内存分析命令 | Memory |
4 | ps进程命令 | Process |
5 | Am命令用法 | Am |
6 | Pm命令用法 | Pm |
7 | 调试系列1:bugreport源码篇 | bugreport |
8 | 调试系列2:bugreport实战篇 | bugreport |
9 | dumpsys命令用法 | dumpsys |
五、结束语
计划: 后续持续新增和完善整个大纲,不限于进程、内存、IO、系统服务框架,整体架构以及各种系统分析实战等文章。 博客会持续更新,各个击破,本文最近更新时间点: 2017.09.03
.
说明:博主水平和精力有限,没有大量的时间反复校验文章,目前只是初稿,后续会不断整理和完善每一篇文章。 另外,如果您发现文章逻辑、文字或表述存在错误,还望海涵,欢迎留言指正、或邮件gityuan@gmail.com,或微博反馈,谢谢!
欢迎大家关注我的微信公众号: Android达摩院
我将跟大家一起在Android达摩院,研究Android系统的各路武学绝技,分享武学秘籍,提升Android内功。
欢迎关注微信公众号: Android达摩院, 微博: weibo.com/gityuan!
【转】Android系统开篇的更多相关文章
- 开篇 Android系统的体系结构
1.APPLICATIONS (应用程序层) 2.APPLICATION FRAMEWORK(应用程序框架) android应用程序提供了大量应用程序供开发者使用,当我看开发android应用程序时 ...
- Android系统全貌 (转)
转自Gityuan的Android开篇,对自我学习作进一步整理. Android系统以Linux内核作为基底,上层采用Native层和Java层.系统分为内核空间和用户空间,并通过系统调用(Sysca ...
- android系统架构解析
以上是我在这个课题下的一些参考博客或者网页链接.里面有对于android架构的一些较好的分析理解,接下来是楼主在阅读后自己的一些整理. Android采用层次化系统架构,官方公布的标准架构如下图所示. ...
- Android系统架构与系统源码目录
前言 技术博客终于可以恢复正常的更新速度了,原因是我编写的进阶书籍的初稿已经完成,窃以为它将会是Android应用书籍中最有深度的一本,可以说是<Android开发艺术探索>的姊妹篇.在这 ...
- 【Android Studio探索之路系列】之中的一个:Android Studio开篇
作者:郭孝星 微博:郭孝星的新浪微博 邮箱:allenwells@163.com 博客:http://blog.csdn.net/allenwells github:https://github.co ...
- 最新Android系统版本与API等级对应关系表
最新Android系统版本与API等级对应关系表 从Android官网拷过来的,方便查阅... 官网地址:https://developer.android.com/guide/topics/mani ...
- android系统release签名
转自:http://blog.csdn.net/yangkai6121/article/details/38682321 为什么需要给Android系统签个名才能进行CTS认证呢?原来我们通过make ...
- Android系统的五种数据存储形式(二)
之前介绍了Android系统下三种数据存储形式,今天补充介绍另外两种,分别是内容提供者和网络存储.有些人可能认为内存提供者和网络存储更偏向于对数据的操作而不是数据的存储,但这两种方式确实与数据有关,所 ...
- Android系统的五种数据存储形式(一)
Android系统有五种数据存储形式,分别是文件存储.SP存储.数据库存储.contentprovider 内容提供者.网络存储.其中,前四个是本地存储.存储的类型包括简单文本.窗口状态存储.音频视频 ...
随机推荐
- lvs三种模式的配置
- c++ stod很慢
C++ Convert String to Double Speed (There is also a string-to-int performance test.) A performance b ...
- 11.6 正睿停课训练 Day17
目录 2018.11.6 正睿停课训练 Day17 A chinese(思路 计数) B physics(单调队列/剪枝 DP) C chemistry(期望 DP) 考试代码 A B C 2018. ...
- Java代码优化小结(二)
(21)将常量声明为static final,并以大写命名 这样在编译期间就可以把这些内容放入常量池中,避免运行期间计算生成常量的值.另外,将常量的名字以大写命名也可以方便区分出常量与变量 (22)不 ...
- Java笔记(七)HashMap和HashSet
HashMap和HashSet 一)HashMap 1.Map接口 interface Map<K,V> { int size();//查看Map中的键值对个数 boolean isEmp ...
- Module not found: Error: Can't resolve 'XXX' in 'XXXX'
故障 控制台运行webpack/npm时出现 Module not found: Error: Can't resolve 'XXX' in 'XXXX' 解决方案 npm i XXX --save ...
- React使用Styled-Componets来添加样式
React使用Styled-Componets来添加样式 Styled-Comonents是用JS中ES6 语法的方式来管理CSS样式的一个组件,解决了在import CSS文件时样式重复 安装 项目 ...
- LINUX文件及目录管理命令基础
Linux命令行组成结构 Linux命令结构 在Linux中一切皆文件,一切皆命令! 命令提示符: [root@tt ~]# [xiaohui@tt ~]$ Linux命令行常用快捷键 ctrl + ...
- JS Function类型
每个函数都是Function类型的实例,由于函数是对象,函数名实际上是一个指向函数对象的指针,不会与某个函数绑定. 1.函数的声明: (1)函数声明语法: function sum (num1,num ...
- UltraEdit使用(工具类似于notepad++)
打开多个文件,在多个文件中切换,鼠标点/ Ctrl+Tab自动换行的设置: 高级-->配置-->编辑器-->自动换行,制表符设置-->默认为每个文件启用自动换行 去掉自动备份设 ...