Android Binder 系列一 :基本概要

一、 linux 进程间通讯概述

  • 管道:在创建时分配一个 page 大小的内存,缓存区大小比较有限;
  • 消息队列:信息复制两次,额外的 CPU 消耗;不合适频繁或信息量大的通信;
  • 共享内存:无须复制,共享缓冲区直接付附加到进程虚拟地址空间,速度快;但进程间的同步问题操作系统无法实现,必须各进程利用同步工具解决;
  • 套接字:作为更通用的接口,传输效率低,主要用于不通机器或跨网络的通信;
  • 信号量:常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
  • 信号: 不适用于信息交换,更适用于进程中断控制,比如非法内存访问,杀死某个进程等;

二、binder 概述

2.1 为什么 android 还要用 binder

        Linux提供有管道、消息队列、信号量、内存共享、套接字等跨进程方式,那为什么Android要选择Binder另起炉灶呢?

2.1.1 传输性能好

  • Socket:是一个通用接口,导致其传输效率低,开销大
  • 共享内存:虽然在传输时不需要拷贝数据,但其控制机制复杂
  • Binder:复杂数据类型传递可以复用内存,需要拷贝1次数据
  • 管道和消息队列:采用存储转发方式,至少需要拷贝2次数据,效率低

2.1.2 安全性高

  • 传统的进程:通信方式对于通信双方的身份并没有做出严格的验证,只有在上层协议上进行架设
  • Binder机制:从协议本身就支持对通信双方做身份校检,因而大大提升了安全性

2.2 binder 是在 android 上进程间通讯的一种方式

结构图

  1. Binder通信机制采用C/S架构;
  2. Binder框架中主要涉及到4个角色Client、Server、Service Manager及Binder驱动,其中Client、Server、Service Manager运行在用户空间,Binder驱动运行在内核空间
  3. Client代表客户端进程,Server代表客户端进程提供各种服务
  4. Service Manager用来管理各种系统服务
  5. Binder驱动提供进程间通信的能力
  6. 用户空间的Client、Server、ServiceManager通过open、mmap和ioctl等标准文件操作来访问/dev/binder,进而实现进程间通信。

2.3 通讯原理

  1. Service 端通过 Binder 驱动在 ServiceManager 的查找表中注册 Object 对象的a dd 方法
  2. Client端通过Binder驱动在ServiceManager的查找表中找到Object对象的add方法,并返回 proxy 对象的add方法,add 方法是个空实现,proxy 对象也不是真正的 Object 对象,是通过 Binder 驱动封装好的代理类的 add 方法
  3. 当Client端调用 add 方法时,Client端会调用 proxy 对象的 add 方法,通过 Binder 驱动去请求ServiceManager 来找到 Service 端真正对象,然后调用 Service 端的 add 方法

2.4 Binder 对象和 Binder 驱动

Binder对象:Binder机制中进行进程间通讯的对象,对于 Service 端为 Binder 本地对象,对于 Client 端为 Binder 代理对象。

Binder驱动:Binder 机制中进行进程间通讯的介质,Binder 驱动会对具有跨进程传递能力的对象做特殊处理,自动完成代理对象和本地对象的转换。

 

2.5 binder 每一层的分析

  1. 从IPC角度来说:Binder是Android中的一种跨进程通信方式,该通信方式在linux中没有,是Android独有;
  2. 从Android Driver层:Binder还可以理解为一种虚拟的物理设备,它的设备驱动是/dev/binder;
  3. 从Android Native层:Binder是创建Service Manager以及BpBinder/BBinder模型,搭建与binder驱动的桥梁;
  4. 从Android Framework层:Binder是各种Manager(ActivityManager、WindowManager等)和相应xxxManagerService的桥梁;
  5. 从Android APP层:Binder是客户端和服务端进行通信的媒介,当bindService的时候,服务端会返回一个包含了服务端业务调用的 Binder对象,通过这个Binder对象,客户端就可以获取服务端提供的服务或者数据,这里的服务包括普通服务和基于AIDL的服务。

2.6 Binder架构

2.7 framework层

1. 采用JNI技术来调用native(C/C++)层的binder架构,从而为上层应用程序提供服务。

2. 红色代表整个framework层 binder架构相关组件;

  • Binder类代表Server端
  • BinderProxy类代码Client端;

3. 上层framework层的Binder逻辑是建立在Native层架构基础之上的,核心逻辑都是交予Native层方法来处理。

4. framework层的ServiceManager类与Native层的功能并不完全对应,framework层的ServiceManager类的实现最终是通过BinderProxy传递给Native层来完成的。

2.8 Binder类图

 

2.8.1 类(class)

 图中白色部分

  1. ServiceManager:通过getIServiceManager方法获取的是ServiceManagerProxy对象; ServiceManager的addService, getService实际工作都交由ServiceManagerProxy的相应方法来处理;
  2. ServiceManagerProxy:其成员变量mRemote指向BinderProxy对象,ServiceManagerProxy的addService, getService方法最终是交由mRemote来完成。
  3. ServiceManagerNative:其方法asInterface()返回的是ServiceManagerProxy对象,ServiceManager便是借助ServiceManagerNative类来找到ServiceManagerProxy;
  4. Binder:其成员变量mObject和方法execTransact()用于native方法
  5. BinderProxy类:是Binder类的内部类,它代表远程进程的Binder对象的本地代理
  6. BinderInternal:内部有一个GcWatcher类,用于处理和调试与Binder相关的垃圾回收

 

2.8.2 接口(Interface)

图中蓝色部分

  1. IBinder:接口中常量FLAG_ONEWAY:客户端利用binder跟服务端通信是阻塞式的,但如果设置了FLAG_ONEWAY,这成为非阻塞的调用方式,客户端能立即返回,服务端采用回调方式来通知客户端完成情况。另外IBinder接口有一个内部接口DeathDecipient(死亡通告)。
  2. IInterface接口:client端与server端的调用契约,实现这个接口,就代表远程server对象具有什么能力,因为IInterface接口的asBinder方法的实现可以将Binder本地对象或代理对象进行返回

 

2.9 Binder类分层

三、Binder内存机制

        虚拟进程地址空间(vm_area_struct)和虚拟内核地址空间(vm_struct)都映射到同一块物理内存空间间。

 

        当Client端与Server端发送数据时,Client(作为数据发送端)先从自己的进程空间把IPC通信数据​copy_from_user​拷贝到内核空间,而Server端(作为数据接收端)与内核共享数据,不再需要拷贝数据,而是通过内存地址空间的偏移量,即可获悉内存地址,整个过程只发生一次内存拷贝。

 

        一般地做法,需要Client端进程空间拷贝到内核空间,再由内核空间拷贝到Server进程空间,会发生两次拷贝。

Binder在进程间数据通信的流程图,从图中更能明了Binder的内存转移关系。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值