Framework
Android系统分成三层:最上层是Application应用层,第二层是Framework层,第三层是Native层。
Android中的应用层和系统服务层不在同一个进程,系统服务在单独的进程中。
- Android中不同应用属于不同的进程中。
- Android应用和系统services运行在不同进程中是为了安全、稳定、以及内存管理的原因,但是应用和系统服务又需要通信和数据共享。
优点:
- 安全性:每个进程都单独运行,可以保证应用层和系统层的隔离;
- 稳定性:某个进程崩溃不会影响其他进程;
- 内存分配:进程不需要时可以直接移除,回收对应内存。
程序中的多进程
虚拟机分配给各个进程的运行内存是有限制的,LMK也会优先回收对系统资源占用多的进程。
多进程的好处:
- 突破进程内存限制:如图库等大内存场景,因为内存分配是按进程来的。
- 功能稳定性:如独立的通信进程用于长连接,避免主进程被干扰。
- 规避系统内存泄漏:如WebView单独进程,避免泄漏拖垮主进程。
- 隔离风险:将不稳定的功能放入独立进程,保护主进程。
现实案例: 腾讯等大型应用内部一般会有多个进程同时运行。
Binder的出现
出身
Binder最早源自OpenBinder项目(由Be公司George Hoffman提出,Dianne Hackborn开发)。后来Dianne Hackborn加入Google,将OpenBinder理念移植到Android中,用来做进程通信。
为什么要学习binder
- startActivity时获取AMS服务,调用其startActivity方法;
- startActivity传递的对象为什么要序列化;
- bindService为什么回调的是一个binder对象;
- 多进程应用如何通信(AIDL的使用)。
Binder是什么?
Binder是Android中的“血管”。所有Activity、Service等组件与AMS(system server)的通信都需要通过Binder。
- 机制:Binder是一种高效进程间通信(IPC)机制;
- 驱动:Binder有内核驱动实现;
- 应用层:Java/Native有相应的Binder类;
- 整体架构:Binder把Client、Server、ServiceManager和Binder驱动连接起来,形成完整的C/S通信架构。
为什么选择Binder?
安卓中的常见IPC方式:
- 共享内存:
用于大块数据传递,如WS与SurfaceFlinger通信、ashmem机制。
传大bitmap通过Intent时可能崩溃,是因为Intent禁掉fd,bitmap没法用共享内存,只能拷贝到Binder缓冲区导致超限;用putBinder可规避此问题。 - 管道:
父子进程通信,需要管道文件,数据是字节流格式,双向拷贝(进程到管道再到另一个进程)。 - 消息队列:
多进程共享内核链表,需约定数据格式和大小。 - Socket:
跨设备/进程通信,如AMS和zygote通信。 - 信号:
用于进程生命周期管理,通信能力极弱。 - Binder:
安卓官方主推,优势在于高效(一次拷贝),权限可控,支持多对多。
说明:所有这些通信方式都需要走内核空间。
Binder线程池:Server与Client通过Binder通信时,每个Client都会建立一个专用的通信线程(Binder线程池)。
各通信方式示意图
共享内存
管道
消息队列
Socket
Binder
方式对比
Binder通信的基本模型
内存划分
- 内存被划分为用户空间和内核空间,两者隔离。即使用户程序崩溃,内核依然安全。
binder是如何管理的
- Client端要与Server端通信,必须获取Server端的Binder。
- Server通常先启动,并注册自身Binder到ServiceManager(SM)。
- ServiceManager维护一个表,包含所有Server的Binder。
- Client通过SM获取目标Binder,再进行通信。
- ServiceManager的handle节点固定为0,类似DNS的8.8.8.8。
Binder是什么时候创建的?
- Binder需要在App启动时第一时间创建,否则无法支持Activity等组件的跨进程通信。
跨进程通信模型
- binder驱动属于Server端,在内核态。
- Java代码通过AIDL生成Java和C++文件,打通Java/Native与Binder驱动通信。
stub/proxy 机制
stub是服务端存根,实现跨进程通信细节;proxy是客户端代理,代理服务端Binder。
- 跨进程调用需用stub的实现类(只有它实现了通信基础代码);
- 客户端bindService时,用Action和package唯一确定服务器Binder对象。
- ServiceConnection回调中的service其实就是服务端的Binder对象(IBinder接口,需要asInterface转换)。
服务注册完整流程
附:AIDL支持生成C++文件(Android 10+)
Android Q(29)及以后,AIDL支持直接生成C++,命令参考:
blog.csdn.net/yinminsumen…
学后检测
一、单选题
1. 下列关于Android进程与Binder通信的说法,正确的是:
A. Android所有应用都运行在同一个进程中
B. Binder是Android特有的进程内通信机制
C. 每个Android应用默认运行在独立进程
D. Android应用和系统服务之间的通信通常通过Binder完成
【答案与解析】
答案:D
解析:A错误,应用各自独立进程;B错误,Binder是IPC(进程间通信)不是进程内通信;C错误,应用可指定进程名,但通常一个应用进程可包含多个组件;D正确,App和系统服务间通信都依赖Binder。
2. 以下哪种不是Binder的直接优势?
A. 低拷贝高性能
B. 内核权限控制
C. 支持Java和C++层的跨进程通信
D. 能跨设备网络通信
【答案与解析】
答案:D
解析:Binder仅限本机进程间通信,不能跨设备。A、B、C都是Binder的优势。
3. Android中的ServiceManager的作用是什么?
A. 管理应用进程的生命周期
B. 管理所有已注册Binder服务的查找和分发
C. 处理Activity与Service的生命周期
D. 提供Java层到Native层的JNI桥接
【答案与解析】
答案:B
解析:ServiceManager是Binder架构中的“服务注册中心”,负责各服务的注册、查找和分发。
二、多选题
4. Android中采用多进程的常见场景包括哪些?
A. WebView内存泄漏隔离
B. 提高UI主线程流畅度
C. 突破单进程内存限制
D. 长连接独立、规避主进程崩溃
E. 系统组件(如AMS/PMS)与App分离
【答案与解析】
答案:A、C、D、E
解析:B选项不准确,多进程不是直接提升主线程流畅度的方法,其它选项均为实际应用场景。
5. 下列哪些属于进程间通信(IPC)方式?
A. 消息队列
B. 共享内存
C. Socket
D. 信号
E. Activity跳转
【答案与解析】
答案:A、B、C、D
解析:E不是IPC,A、B、C、D都是常见IPC机制。
6. 关于Binder机制的特点,以下说法正确的是?
A. 数据通过mmap只需一次拷贝
B. 每个Client通信会自动分配线程池
C. 可以对传输数据进行权限校验
D. 支持大容量bitmap数据无限制传输
【答案与解析】
答案:A、B、C
解析:D错误,binder数据大小受限(如1M-8K),传输大数据会失败。
三、判断题
7. 通过AIDL实现进程通信时,client和server端的aidl接口及包名路径必须完全一致。 ( )
A. 正确
B. 错误
【答案与解析】
答案:A
解析:只有接口、包名、方法一致,序列化反序列化才不会出错。
8. Binder机制支持Java和Native(C++)两种开发方式。 ( )
A. 正确
B. 错误
【答案与解析】
答案:A
解析:Android 10以后AIDL支持直接生成C++代码,Java/Native都支持。
9. Socket通信和Binder通信本质上都要经过内核空间。 ( )
A. 正确
B. 错误
【答案与解析】
答案:A
解析:所有IPC数据传递都需进出内核空间。
四、简答题
10. 请简述Binder相比传统IPC机制(如管道、消息队列、Socket)的优势。
【答案与解析】
- 拷贝次数更少,借助mmap提升性能。
- 支持权限校验、安全性高,适合多用户场景。
- 线程池+驱动层支持高并发。
- 统一服务注册/查找,便于系统服务管理和扩展。
- 既可支持小对象高频RPC,又支持(有限)大对象共享。
11. 为什么传递大对象(如bitmap)时,Intent可能导致异常?如何规避?
【答案与解析】
- Intent传递大对象时,若bitmap过大,不能走共享内存,只能拷贝到Binder缓冲区,容易超限(1M-8K),系统会抛出异常。
- 正确做法:用文件共享或共享内存(ashmem)、或用putBinder(允许fd),规避Intent禁用fd机制的限制。
五、编程题
12. 设计一个多进程AIDL服务注册/通信的伪代码结构,说明Stub/Proxy的典型角色。
【答案与解析】
Server端:
// IMyAidlInterface.aidl
package com.example.aidl;
interface IMyAidlInterface {
void doSomething();
}
// Service实现
public class MyService extends Service {
private final IMyAidlInterface.Stub binder = new IMyAidlInterface.Stub() {
public void doSomething() { /* 业务实现 */ }
};
@Override
public IBinder onBind(Intent intent) { return binder; }
}
Client端:
// ServiceConnection回调
public void onServiceConnected(ComponentName name, IBinder service) {
IMyAidlInterface api = IMyAidlInterface.Stub.asInterface(service);
api.doSomething();
}
Stub是服务端存根,Proxy是客户端远程代理,IBinder是两者通信的桥梁。
六、应用与原理分析题
13. 简要描述App通过Binder机制从启动到调用系统服务(如AMS)的典型时序流程。
【答案与解析】
- App启动时Zygote fork新进程,创建自身Binder实体。
- 系统服务(AMS/PMS等)启动后注册到ServiceManager。
- App进程通过ServiceManager获取系统服务的Binder引用。
- App通过Binder驱动将请求发往系统服务进程,由Binder线程池接收和分发。
- 系统服务处理后通过Binder驱动回传结果,完成一次完整的IPC调用。