Framework学习:周末小总结以及Binder基础
文章目录
- Framework学习:周末小总结以及Binder基础
-
- 背景:
- 一、Android系统架构概览
- 二、Binder机制:跨进程通信的核心
-
- [1. 基本定位](#1. 基本定位)
- [2. 与相关技术的关系](#2. 与相关技术的关系)
- [3. 核心特性](#3. 核心特性)
- [4. 运行空间](#4. 运行空间)
- 三、核心进程与启动流程
- 四、Framework与Native层的关系
- 五、Framework开发核心与学习思路
背景:
对上周学的一些源码和一些流程进行回顾,主要在系统启动方面,还有一些binder的基础,因为binder涉及到的知识面太多了,可能流程会比较长而且会插入一下别的东西的学习。
一、Android系统架构概览
- 层次结构 (以音频为例):
硬件层 → 驱动层 → HAL层(硬件抽象层) → Native层(C/C++) → JNI层 → Java Framework层 → 应用层- HAL层:对硬件进行抽象封装,提供统一接口给Native层调用,隔离硬件差异。
- Framework层:包含大量系统服务(如Audio、Bluetooth、WiFi、WMS等),提供Java API给应用调用。
- AOSP vs Framework:AOSP是Android开源项目的完整源码,Framework是AOSP中的核心框架部分(含系统服务、API等)。
二、Binder机制:跨进程通信的核心
1. 基本定位
Binder是Android最核心的IPC机制,连接系统中各个进程(如应用进程与系统服务进程),解决进程内存隔离导致的通信问题。
2. 与相关技术的关系
- AIDL:Android接口定义语言,自动生成Binder通信的Java/C++代码(代理Proxy与Stub),简化跨进程调用实现。
- HIDL:硬件接口定义语言,用于HAL层与Framework层的通信,底层依赖Binder机制(Android 8.0后逐步替代旧的HAL与Binder交互方式)。
3. 核心特性
- 高效传输:通过内存映射(mmap)实现一次数据拷贝(传统IPC需两次),适合高频通信(如系统服务调用)。
- C/S架构 :
- Server(服务端):提供服务的进程(如SystemServer),通过Binder注册服务。
- Client(客户端):使用服务的进程(如应用),通过Binder获取Server的代理对象(Proxy)。
- Binder驱动:内核层中间件,负责转发请求、管理连接、验证进程身份(UID/PID)。
- 安全性:通信时自动携带进程UID/PID,Server可基于权限控制是否响应(如SMS服务校验发送权限)。
4. 运行空间
- Binder跨用户空间与系统空间工作:
- 系统空间:idle进程及以上的内核态进程。
- 用户空间:init进程(第一个用户空间进程)、应用进程、系统服务进程等,Binder的客户端/服务端实现运行在此。
三、核心进程与启动流程
-
Init进程:
- 用户空间第一个进程,通过加载
init.rc
脚本启动关键进程(如ServiceManager、Zygote)。 - 常驻后台,通过
epollwait
阻塞等待事件(若无任务则休眠),保证系统稳定性。
- 用户空间第一个进程,通过加载
-
ServiceManager:
- Binder机制的"服务注册表",管理所有系统服务的注册与查询(Client需先通过它获取Server的Binder代理)。
- ServiceManager 是 Android 中第一个注册的 Binder 服务,自身没有 Proxy,直接通过binder_loop循环处理请求。
其他服务(如 AMS、WMS)必须先向 ServiceManager 注册(addService()),Client 需先通过 ServiceManager 查询(getService())获取目标服务的 Binder 引用。
补充流程:Client→ServiceManager(查服务)→目标 Server(通过 Binder 通信)。
-
Zygote进程:
- 作用:孵化应用进程(通过
fork
快速创建新进程,共享虚拟机资源)。 - 特性:同时运行Java与Native(C/C++)代码:
- Native层:启动ART虚拟机(设置堆大小等参数,参数来自设备property文件),ART是Android的虚拟机(替代传统JVM,更适合移动设备)。
- Java层:执行
Zygote.main()
,读取启动参数,准备应用进程孵化环境。
- 作用:孵化应用进程(通过
java
zygote.main() {
// 1. 初始化启动参数
// 从启动进程的参数(如init.rc传递的args)中解析配置
// 包括:进程名称、虚拟机启动参数、预加载资源列表路径等
String[] argv = parse启动参数(); // 解析init进程传递的命令行参数
String processName = 从argv中提取进程名(); // Zygote进程名通常为"zygote"或"zygote64"
// 2. 启动Native层运行时环境(AndroidRuntime)
// 这是连接Java层与Native层的桥梁,负责初始化底层资源
AndroidRuntime runtime = new AndroidRuntime();
runtime.initNativeEnv(); // 初始化Native层环境(如C库、线程池等)
// 3. 启动ART虚拟机(Android Runtime)
// 虚拟机参数从系统属性(build.prop等)读取,不同设备配置不同
// 例如:dalvik.vm.heapstartsize(初始堆大小)、dalvik.vm.heapsize(最大堆大小)
String[] vmArgs = 从系统属性读取虚拟机参数();
runtime.startVm(vmArgs); // 启动ART虚拟机(基于C/C++实现,替代传统JVM)
// 注:ART是Android专用虚拟机,支持AOT编译,性能优于JVM,更适合移动设备
// 4. 注册JNI方法(Java与Native代码的映射)
// 静态注册:通过方法名规则(Java_包名_类名_方法名)自动关联
// 动态注册:通过RegisterNatives()主动注册映射关系(更高效,系统框架常用)
runtime.registerJniMethods(); // 注册Framework层核心类的JNI方法
// 例如:java.lang.String的native方法与C++的String.cpp实现关联
// 5. 预加载核心类与资源(关键优化点)
// 提前加载系统Framework类(如android.app.*)、主题资源、共享库等
// 后续通过fork创建应用进程时,可直接复用这些已加载资源,减少重复开销
preloadClasses(); // 预加载系统类(从preloaded-classes文件读取列表)
preloadResources(); // 预加载系统资源(如framework-res.apk)
// 6. 启动Socket服务,等待孵化新进程的请求
// Zygote通过本地Socket接收AMS(ActivityManagerService)的进程创建请求
ZygoteServer server = new ZygoteServer();
server.createSocket(); // 创建本地Socket(路径通常为/dev/socket/zygote)
server.runSelectLoop(); // 进入循环,阻塞等待新进程孵化请求
// 收到请求后通过fork()创建子进程(应用进程),并复用Zygote的虚拟机资源
}
fork后,子进程(应用进程)会调用handleChildProc(),销毁 Zygote 的 Socket 连接(避免冲突),重置进程 ID 和权限。
启动应用进程的主线程(ActivityThread.main()),通过 JNI 调用ActivityThread.attach(),与 AMS 建立 Binder 通信(注册应用进程)。
补充:Zygote 通过 "写时复制(COW)" 机制复用内存,fork后仅当子进程修改数据时才复制内存页,优化资源占用。
四、Framework与Native层的关系
-
Native层定位:
- 属于用户空间,用C/C++编写,处理高性能需求场景(如大图片跨进程传输、音视频编解码)。
- 与Framework层通过JNI(Java Native Interface)交互:JNI负责映射Java方法与Native函数,实现跨语言调用。
-
混淆点澄清:
- Native层≠系统空间:Native是用户空间中使用C/C++的代码层,与Java层同属用户空间。
- JVM并非应用底层:Android应用依赖ART虚拟机(Native层实现),JVM是传统Java虚拟机,不适用于Android。
-
具体案例
- 以 "获取屏幕亮度" 为例:
App 调用Settings.System.getInt(getContentResolver(), SCREEN_BRIGHTNESS)(Java Framework)→
通过 JNI 调用android_os_Settings_System.cpp(Native 层)→
调用 HAL 层的ILightService(通过 HIDL/Binder)→
最终操作硬件驱动。
- 以 "获取屏幕亮度" 为例:
五、Framework开发核心与学习思路
-
Framework开发目的 :
解决系统级问题(如WMS处理多应用闪屏),优化系统服务性能或扩展功能。
-
学习路径:
- 源码阅读:理解系统服务(如AMS、WMS)的实现逻辑,重点关注Binder通信流程。
- 实践:编写AIDL接口,编译运行验证跨进程调用;修改Framework源码(如系统服务),重新编译验证效果。
- 架构理解:梳理各层依赖关系(如HAL→Native→Framework的调用链),明确Binder在其中的桥梁作用。