Binder的概述:
- Binder是干嘛的?
- 为什么选择Binder作为最主要的IPC通信机制
- 绘制Binder的通信架构图,讲述原理
- 手写一个AIDL
Linux系统的通信方式
先介绍Linux进程通信的方式:
- 管道
- Socket
- 共享内存
- 信号
1、管道
- 半双工,单向的,数据只能在一个方向流,要么读,要么写 pipe(fds):Linux提供的api,可以生成两个字符,一个读一个写
- 一般在父子进程之间使用 (无名管道)
- 如果知道管道名字,两个进程可以交互
原理图: 先生成两个描述符:读写。 操作的时候会关一个
2、Socket 注意:本地的socket不是网络的sokcet
- 全双工的,可读可写
- 任意两个进程都可以进程交互
- 创建的时候需要指定一个路径,只要公开路径就可以进行通信了
共享内存
- 很快,不需要多次拷贝
- 拿到文件描述符,直接映射到两个进程的内存空间,一个进程往里面写,另一个就能得到
信号
- 单向的,发出去之后怎么处理是别人的事
- 只能带个信号,不能带别的参数
- 知道进程的pid,就可以发信号了,一次可以群发。
- 注意有权限限制,要么root权限, 要么同一个进程uid相同
总结:
- 进程间通信其实还有两个因素: 性能、传输效率和安全
管道: 性能、效率问题,采用内存缓冲的方式,先从发送方的缓冲区拷贝到内核开辟的缓存区,在从内核缓冲区拷贝到接收方的缓冲区,至少拷贝两次。
Sokcet: 传输效率低,开销比较大,也存在安全问题。Android为每个应用分配一个UID,所以UID是标记进程的方式,但是这个会放在数据包中,可以被恶意的拦截,进行随意的入侵。
共享内存: 虽然不需要拷贝,但是也存在安全的问题。
总结:所以Android需要一种高效、安全性能高的通信方式! Binder做到的安全:ipc标记在内核中添加
二、进程隔离
为什么要设计进程隔离?
进程之间是无法直接进行交互的,每个进程独享自己的数据。 主要是为了保证 自身系统的安全稳定性,将系统内核空间和用户空间分开来,保证用户进程崩溃时,不会影响整个系统。
用户空间和内核空间
用户空间(不可共享空间):表示进程运行在一个特定的操作模式中,没有接触物理内存或设备的权限
内核空间(可共享空间):表示独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限
总结: 为了保证安全性,他们之间是隔离的,所以用户空间的进程要进行交互,需要通过内核。
- Linux的虚拟内存机制导致内存的隔离,进而导致进程隔离
- 进程隔离的出现导致对内存的操作被划分为用户空间和内核空间
- 用户空间需要跨权限去访问内核空间,必须使用系统调用去实现
- 系统调用需要借助内核模块/驱动去完成
三、C/S结构
四、Binder通信模型:
Binder基于C/S的结构下,定义了4个角色:Server、Client、ServerManager、Binder驱动,其中前三者是在用户空间的,也就是彼此之间无法直接进行交互,Binder驱动是属于内核空间的 ,属于整个通信的核心,虽然叫驱动,但是实际上和硬件没有太大关系,只是实现的方式和驱动差不多,驱动负责进程之间Binder通信的建立,Binder在进程之间的传递,Binder引用计数管理,数据包在进程之间的传递和交互等一系列底层支持。
从上图很清晰的可以看出来整个的交互过程,原本从SM中拿到binder的引用,通过Binder驱动层的处理之后,返回给了client一个代理对象,实际上如果client和server处于同一个进程,返回的就是当前binder对象,如果client和server不处于同一个进程,返回给client的就是一个代理对象
自己写一个跨进程通信:
首先先理解几个关键词的概念:
IBinder : IBinder 是一个接口,代表了一种跨进程通信的能力。只要实现了这个借口,这个对象就能跨进程传输。
IInterface : IInterface 代表的就是 Server 进程对象具备什么样的能力(能提供哪些方法,其实对应的就是 AIDL 文件中定义的接口)
Binder : Java 层的 Binder 类,代表的其实就是 Binder 本地对象。BinderProxy 类是 Binder 类的一个内部类,它代表远程进程的 Binder 对象的本地代理;这两个类都继承自 IBinder, 因而都具有跨进程传输的能力;实际上,在跨越进程的时候,Binder 驱动会自动完成这两个对象的转换。
Stub : AIDL 的时候,编译工具会给我们生成一个名为 Stub 的静态内部类;这个类继承了 Binder, 说明它是一个 Binder 本地对象,它实现了 IInterface 接口,表明它具有 Server 承诺给 Client 的能力;Stub 是一个抽象类,具体的 IInterface 的相关实现需要开发者自己实现。
public interface PersonManger extends IInterface {
void addPerson(Person mPerson);
List<Person> getPersonList();
}
// server端的binder实体对象,其实就是aidl自动生成的Stub对象
public abstract class BinderObj extends Binder implements PersonManger {
public static final String DESCRIPTOR = "com.example.taolin.hellobinder";
public static final int TRANSAVTION_getPerson = IBinder.FIRST_CALL_TRANSACTION;
public static final int TRANSAVTION_addPerson = IBinder.FIRST_CALL_TRANSACTION + 1;
public static PersonManger asInterface(IBinder mIBinder){
IInterface iInterface = mIBinder.queryLocalInterface(DESCRIPTOR);
if (null!=iInterface&&iInterface instanceof PersonManger){
return (PersonManger)iInterface