概述
站在巨人的肩膀上学习,本片博客参考
gityuan,用于笔记和巩固知识
Android 架构
这个是Google官方提供的经典的分层架构图,从下向上依次是,Linux内核,HAL,系统Native库和Android Runtime,Java框架层,应用层,其中每一层都有若干的子模块和子系统
Google提供的5层很经典,但是为了更进一步的透视Android 系统架构,以进程的视角,以分层的架构,来诠释Android的全貌,诠释Android 全貌的内在联系
Android 启动架构图
Android 系统启动过程由上图从下向上的一个过程,由Boot Loader引导开机,然后依次进入Kernel
-> Native
-> Framework
-> App
,下面简要介绍这几个过程
开机(关于Loader层)
- Boot ROM:当手机处于关机的状态,长按Power键开机,引导芯片从固化在
ROM
里预设的代码开始执行,然后加载程序到RAM
- Boot Loader:这是启动Android系统之前的引导程序,主要是检查RAM,初始化硬件参数等工能
关于Kernel (Linux内核层)
Android 平台的基础是Linux内核,比如ART虚拟机最终调用的是Linux内核执行的功能,Linux内核的安全机制为Android提供相应的保障,也允许设备制造商为内核开发硬件驱动程序
- 启动Kernel的swapper进程(pid=0),该进程又称为idle进程,系统初始化过程Kernel从无到有,开创的第一个进程,用于初始化进程管理,内存管理,加载Display,Camera Driver,Binder Driver,等相关工作
- 启动kthreadd进程(pid=2),是Linux的内核进程,会创建内核工作线程kworkder,软中断线程ksoftirqd,thermal等内核守护进程,
kthreadd进程是所有内核进程的鼻祖
关于硬件抽闲层(HAL)
硬件抽象层(HAL)提供标准接口,HAL包括多个库模块,每个模块都为特定的硬件组件实现一组接口,比如Wifi/蓝牙模块,当框架API请求访问硬件时,Android系统将为该硬件加载相应的库模块
Android Runtime 和 系统库
每个应用都在自己的进程中运行,都有自己的虚拟机实例,ART通过执行dex文件可在设备能运行多个虚拟机,DEX文件是专门为Android设计的字节码格式,经过优化使用的内存很小,ART主要包括的工能是,预先(AOT)和即时(JIT)编译
,优化垃圾回收(GC),以及调试相关支持
这里的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进程孵化出来的
Framework层
- Zygote进程,是由init进程通过解析init.rc文件后fork生成的,Zygote进程主要包括
- 加载Zygoteinit类,注册Zygote Socket服务端套接字
- 加载虚拟机
- 提前加载类PreloadClasses
- 提前加载资源PreLoadResouces
- System Server 进程,是由Zygote fork而来,
System Server是Zygote孵化出的第一个进程
,System Server 负责启动和管理整个Java FrameWork,包含ActivityManagerService, WorkManagerService,PagerManagerService,PowerManagerService等服务 - Media Server 进程,是由init fork而来,负责启动和管理整个C++FrameWork,包含AudioFlinger,Camera Service等
App层
- Zygote 孵化出的第一个App进程是Launcher,这是用户看到的桌面App
- Zygote 还会创建出Browser,Phone,Email等App进程,每个App至少运行在一个进程上
- 所有的App进程都是由Zygote fork而成
Syscall && JNI
- Native 和 KerNel之间有一层系统调用(Syscall)
- Java 层和Native层之间的纽带JNI
重要的进程
Android 系统中极其重要的进程,init
,Zygote
,ServiceMager
,system_server
init 进程
-
Linux系统中用户空间的第一个进程init.main
-
init进程还启动了
ServiceManager进程
(Binder的管家),bootanim
(开机动画)等重要服务 -
init 进程还孵化除了
Zygote进程
,Zygote进程是Android中的第一个Java进程(即虚拟机进程)
,Zygote是所有Java进程的父进程
,Zygote进程本身就是init进程孵化出来的
Zygote进程
-
所有App的父进程,ZygoteInit.main
-
Zygote进程,是由init进程通过解析init.rc文件后fork生成的,Zygote进程主要包括
- 加载Zygoteinit类,注册Zygote Socket服务端套接字
- 加载虚拟机
- 提前加载类PreloadClasses
- 提前加载资源PreLoadResouces
-
system_server进程,是由Zygote fork而来,
System Server是Zygote孵化出的第一个进程
,System Server 负责启动和管理整个Java FrameWork,包含ActivityManagerService, WorkManagerService,PagerManagerService,PowerManagerService等服务
system_server进程
系统各大服务的载体, SystemServer.main
system_server进程从源码角度来看可以分为,引导服务,核心服务和其他服务
- 引导服务(7个):ActivityManagerService、PowerManagerService、LightsService、DisplayManagerService、PackageManagerService、UserManagerService、SensorService;
- 核心服务(3个):BatteryService、UsageStatsService、WebViewUpdateService;
- 其他服务(70个+):AlarmManagerService、VibratorService等。
ServiceManger进程
bInder服务的大管家
ServiceManager 是Binder IPC通信过程中的守护进程,本身也是一个Binder,但是并没有采用多线程模型来跟Binder通信,而是自行编写了binder.c直接和Binder驱动来通信,并且只有一个binder_loop来读取和处理事务,这样做的好处是简单和高效
ServiceManager本身工作相对简单,其工能查询和注册服务
流程图
ServiceManager 集中管理系统内的所有服务,通能过权限控制进程是否有权注册服务,通过字符串来查找是否有对应的Service,由于ServiceManager进程注册了Service的死亡通知,那么服务所在的进程死亡后,只需告诉ServiceManager,每个Client通过查询ServiceManager可以获取Service的情况
启动主要包括以下几个阶段
- 打开Binder驱动,并调用mmap()方法分配128k的内存映射空间,binder_open
- 注册成为Binder服务的大管家binder_become_context_manager
- 验证selinux权限,判断进程是否有权注册查看指定服务
- 进入无限循环,处理Client发来的请求 binder_loop
- 根据服务的名称注册服务,重复注册会移除之前的注册信息
- 死亡通知,当所在进程死亡后,调用binder_release方法,然后调用binder_node_release,这个过程发出死亡通知回调
App进程
- 通过Process.start启动的App进程ActivityThread.main
- Zygote 孵化出的第一个App进程是
Launcher
,这是用户看到的桌面App - Zygote 还会创建出
Browser
,Phone
,Email
等App进程,每个App至少运行在一个进程上 - 所有的App进程都是由
Zygote fork
而成
进程与线程的区别
进程:每个App启动前必须先创建一个进程,该进程是由Zygote fork
出来,进程具有独立的资源空间,用于承载App运行的各种Activity/Service组件,进程对于上层的应用层来说是完全透明的,这也是Google刻意为之,让App程序都运行在Android Runtime,大多数情况一个App运行在一个进程中,除非在AndroidManifest.xml文件中配置了Android:process
,或者通过Native代码fork进程
线程:线程对于我们来说比较熟悉,比如每次new Thread().start,都会创建一个新的线程,该线程没有自己的独立空间,而是与所在的进程资源共享,从Linux来说,进程与线程都是task_struct结构体,除了是否资源共享外,没有任何区别
看一下进程创建的过程
- App发起进程:如果从桌面启动应用,则发起进程便是Launcher所在的进程,当从某App启动远程进程,则发起进程是App所在的进程,发起进程首先需要通过Binder发送信息给system_server进程
- system_server进程:调用Process.start方法,通过Socket向Zygote进程发送新建进程的请求
- zygote进程:在执行
ZygoteInit.main()
后进入runSelectLoop()
循环体,当有客户端连接时,便会执行ZygoteConnection.runOnce()
方法,再经过层层调用后fork出新的应用进程 - 新进程:执行
handleChildProc
方法,设置进程名,打开binder驱动,启动新的binder线程,设置art虚拟机参数,反射目标类的main方法,即调用ActivityThread.main()
方法
Process.start()方法是阻塞方法,等待直到进程创建完成返回响应的pid,才完成该方法