跳至主要內容

Android Binder一知半解

PPLong大约 3 分钟

Binder通信机制

基础

Linux通信机制: 管道、信号量、消息队列、共享内存、Socket、信号

进程隔离

进程有自己独享的空间,同时OS将系统空间分为内核空间和用户空间,以此保证内核安全。内核空间是所有进程可共享的。用户空间与内核空间的交互需要通过系统调用,主要通过函数copy_from_user与copy_to_user进行。传统的跨进程通迅需要拷贝两次,即将数据从发送进程用户空间拷贝到内核空间,再将数据从内核空间拷贝到接受进程的用户空间

Binder特点:基于C/S机制。

Binder优点

  • 高效:Binder只需拷贝1次数据(使用内存映射)
  • 安全性高:Binder为每个进程分配了UID和PID作为鉴别身份的标识,在通信时会对其进行检测
  • 采用C/S架构并实现面向对象的调用方式

Binder本质上做了什么事:连接两个进程,实现mmap系统调用,负责创建数据接收的缓存空间并管理数据接收缓存(可能扩容等)

Binder本意有胶水、粘合剂之意,Android中Binder是一个可跨进程引用的对象,各进程都可以获取该binder进行进程通信

通信模型

Binder机制中包含4个角色:

  • Server(用户空间)
  • Client(用户空间)
  • ServerManager(用户空间):属于用户空间的进程,管理Service的注册与查询,将字符形式的Binder名字转化为Client中对该Binder的引用。作为Server和Client的桥梁,Client通过ServerManager拿到Sever中Binder的引用
  • Binder驱动(内核空间):跨进程通讯的介质
  • (实际使用时还使用到Service帮助Client与Service进行通信)
通信模型角色图
通信模型角色图

大致流程

  1. Binder驱动创建一块接收缓存区
  2. 实现地址映射关系,根据需映射的接收进程的信息,将内核缓存区域加收进程用户空间地址映射到1个共享接收缓存区中
  3. 发送进程 调用copy_from_user发送数据到缓存区
具体流程示意图
具体流程示意图

使用

Google Android AIDL教程open in new window

AIDL(Android Interface Definition Language),一种接口定义语言,自动生成可以在Android设备上两个进程之间进行进程通信(IPC)的代码

由于AIDL只支持数据类型:基本类型(int,long,char,boolean等),String,CharSequence,List,Map,其他类型必须使用import导入,即使它们可能在同一个包。自定义类型要实现Parcelable接口(因为拷贝是基于内存的拷贝,而不是硬盘)

Server端

  1. 定义功能接口(用于进程间通信定义的通用接口),AS自动生成该接口的AIDL的接口对象,继承于IInterface
  2. 实现自动生成接口中的抽象类Stub并重写方法,Binder的派生类,重写onTransact方法,对数据进行处理并写入结果
  3. 公开此接口,继承Service接口,在onBind时返回binder(即Stub对象)。即通过bind返回该Stub实例

客户端

  1. 需要将服务端工程的AIDL文件夹下所有内容拷贝到客户端工程对应位置
  2. 通过Server APP的包名获取到服务端Service
  3. 服务端在onServiceConected回调中收到IBinder时,应当调用IBinder的asInterface放啊,将返回的参数转化为指定类型

源码探究