Android Framework重要服务之Binder(一) 概述
一、什么是Binder
简单地说,Binder是Android平台上的一种跨进程交互技术。该技术最早并不是由Google公司提出的,它的前身是Be Inc公司开发的OpenBinder,而且在Palm中也有应用。后来OpenBinder的作者Dianne Hackborn加入了Google公司,并负责Android平台的开发工作,所以把这项技术也带进了Android。
在Android的中,我们知道每个应用都是一个独立的进程,有一个独立的虚拟机,应用和应用之间的内存是不能共享数据的,但是我们用到Activity、Service、Context、provider等功能时恰恰需要大量的数据传输,这种进程间通信的机制被称为:IPC(Inter-Process Communication)。
在Android中常常使用的进程间通信有 共享内存、管道、信号处理、socket、Binder等。每个通信方式都有各自的优缺点,Android通常在合适的地方使用合适的通信方式,比如:内核和用户空间常用的是共享内存机制,一些低数据传输使用socket处理,应用进程之间传输使用Binder机制。
本章将概述Binder的机制原理。
二、Binder作为Android IPC的优势
Linux进程间通信有很多方式,这里大概总结一下这些进程间通信方式的特点:
方式 | 特点 |
---|---|
管道 | 在创建时分配一个page大小的内存,缓存区大小比较有限; |
消息队列 | 信息复制两次,额外的CPU消耗;不合适频繁或信息量大的通信; |
共享内存 | 无须复制,共享缓冲区直接付附加到进程虚拟地址空间,速度快;但进程间的同步问题操作系统无法实现,必须各进程利用同步工具解决; |
套接字 | 作为更通用的接口,传输效率低,主要用于不通机器或跨网络的通信; |
信号量 | 常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。 |
信号 | 不适用于信息交换,更适用于进程中断控制,比如非法内存访问,杀死某个进程等; |
从上表可以看出,Android之所以选择Binder作为通过IPC方式主要基于一下几个方面的优点:
性能角度(数据拷贝次数):共享内存(0)< Binder(1)< 管道/消息队列/Socket(2)
稳定性角度:Binder是基于C/S架构的,结构清晰,两端相对独立。而共享内存实现方式复杂,没有客户与服务端之别, 需要充分考虑到访问临界资源的并发同步问题,否则可能会出现死锁等问题;从这稳定性角度看,Binder架构优越于共享内存。
安全性角度:传统Linux IPC无任何保护措施,完全由上层协议来确保,另外无法鉴别对方进程身份。 Binder机制对于通信双方的身份是内核进行校检支持的,可以获得对方进程可靠的UID/PID,做安全访问控制。
三、Binder的划分
在Android 8.0 之前,Binder机制比较简单,只有一个驱动设备"/dev/binder",一个守护进程"/system/bin/servicemanager",一个binder库"/system/lib64/libbinder.so"。
在Android 8.0开始,Android引入了Treble的机制,为了方便Android系统的快速移植、升级,提升系统稳定性,Binder机制被拓展成了"/dev/binder", "/dev/hwbinder","/dev/vndbinder"。
我们原先使用的"/dev/binder",成为框架进程的专有节点,这意味着供应商进程无法再访问此节点。供应商进程可以访问 /dev/hwbinder,但必须将其 AIDL 接口转为使用 HIDL。
对于想要继续在供应商进程之间使用 AIDL 接口的供应商,需要使用 /dev/vndbinder(而非 /dev/binder)。
Android8.0及之后的Binder域如下表所示:
IPC域 | 说明 |
---|---|
/dev/binder | 框架/应用之间的IPC,使用AIDL接口 |
/dev/hwbinder | 框架/供应商之间的IPC和供应商进程间的IPC,使用HIDL接口 |
/dev/binder | 供应商/供应商之间的IPC,使用AIDL接口 |
四、三种Binder介绍以及之间的联系
1. Binder
在Android 8.0之前,Binder机制比较简单,只有一个Binder。Java层继承Binder,Native C/C++层继承Bbbinder,然后通过servicemanager进程注册实名Binder,然后通过已经创建好的Binder接口传递匿名Binder对象,拿到BinderProxy或者BpBinder以后,就可以Binder通信了。
在Android 8.0后,这个Binder机制继续保留,/dev/binder 设备节点成为框架进程的专有节点,这意味着供应商进程无法再访问此节点。
如果你是系统厂商,在system分区有进程,/dev/biner机制还是可以继续使用,但是你的进程在vendor分区,那只能使用/dev/hwbinder 或者/dev/vndbinder。
Binder机制需要两个进程都同属于System分区。
2. VndBinder
Android8.0 支持供供应商服务使用的新 Binder 域,访问此域需要使用 /dev/vndbinder(而非 /dev/binder)。为了显示 /dev/vndbinder,请确保内核配置项 CONFIG_ANDROID_BINDER_DEVICES 设为 "binder,hwbinder,vndbinder"(这是 Android 通用内核树的默认设置)。vndbinder和binder共用libbinder这个系统库,只是在守护进程和内核空间有一些区别,整体代码流程和使用方式基本一致。
Java层继承Binder,Native C/C++层继承Bbbinder,通过vndservicemanager进程注册实名Binder,然后通过已经创建好的Binder接口传递匿名Binder对象,拿到BinderProxy或者BpBinder以后,就可以Binder通信了。
和Binder的区别,就是device变成了"/dev/vndbinder", 守护进程变成了"vndservicemanager"
通常,供应商进程不直接打开 Binder 驱动程序,而是链接到打开 Binder 驱动程序的 libbinder 用户空间库。为 ::android::ProcessState() 添加方法可为 libbinder 选择 Binder 驱动程序。供应商进程应该在调用 ProcessState,、IPCThreadState 或发出任何普通 Binder 调用之前调用此方法。
binder和vndbiner的机制共用一套libbinder,因此两者使用时,每次只能指定一个设备节点,不能同时使用。
VndBinder机制需要两个进程都同属于Vendor分区。
3. HwBinder
hwbinder和 binder\vndbinder又有所区别,hwbinder是一套全新的流程,有单独的驱动设备"/dev/hwbinder",独立的守护进程"hwservicemanager",独立的SDK-"libhwbinder"。
HwBinder机制可以跨System和Vendor分区使用。
以上三中Binder各自有各自的使用要求,总结起来如下:
IPC域 | 使用要求 |
---|---|
Binder | 供应商无法访问,使用时需要两个进程都同属于System分区 |
VndBinder | 需要两个进程都同属于Vendor分区 |
VndBinder | 可以跨System和Vendor分区使用 |
五. 总结
Android引入Treble机制后,扩展了一个vendor分区,为了能够快速的进行升级,做了隔离HAL层的机制,为了System/System、System/Vendor、Vendor/Vendor 之间进行不同的进程间通信,把原有的Binder机制拆分成了Binder、HwBinder、VndBinder。
Binder和VndBinder 共用一套libbinder、servicemanager的代码,使用AIDL接口,两者不能共存。
HwBinder采用了单独的libhwbinder、hwservicemanager的代码,单独管理,使用HIDL接口。
三者之间互不干扰,在方便系统升级的同时,又提升了系统的安全和稳定性。
作者:wise丰
链接:https://juejin.cn/post/7056301924634591240