Android Framework: Binder(1)-Android IPC

来源:互联网 发布:java开发平台结构图 编辑:程序博客网 时间:2024/06/03 21:17

Android Framework: Binder(1)-Android IPC

两个进程之间交换数据的过程称为IPC(Interprocess communication)跨进程通信。
一种是应用自身需要采用多进程实现,由于某些特许原因应用的某些模块需要运行在独立进程中,如守护进程;
另一种是当前应用需要获取其他应用的数据,由于是两个应用,通信时必须采用跨进程的方式。

一、linux与Android中的IPC机制

linux中现有的IPC方式有:
传统IPC:无名pipe, signal, trace, 有名pipe
AT&T Unix 系统V:共享内存,信号灯,消息队列
BSD Unix:Socket

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

而在Android中,并没有使用这些,取而代之的是Binder机制。binder采用C/S的通信模式。
Binder机制是采用OpenBinder演化而来,在Android中使用它的原因有很多,最主要的原因便是binder相比之下:
1. 性能更高,Binder数据拷贝只需要一次,而管道、消息队列、Socket都需要2次,但共享内存方式一次内存拷贝都不需要;从性能角度看,Binder性能仅次于共享内存。
2. 稳定性更强,Binder是基于C/S架构的,Client端有什么需求,直接发送给Server端去完成,架构清晰明朗,Server端与Client端相对独立,稳定性较好;而在linux通信机制中,目前只有socket支持C/S的通信模式,但socket有其劣势。
3. 安全性更好,传统Linux IPC的接收方无法获得对方进程可靠的UID/PID,从而无法鉴别对方身份;Android系统中对外只暴露Client端,Client端将任务发送给Server端,Server端会根据权限控制策略,判断UID/PID是否满足访问权限,

为什么 Android 要采用 Binder 作为 主要IPC 机制,可以参考以下几篇大神博客:
https://www.zhihu.com/question/39440766?sort=created
http://blog.csdn.net/shareus/article/details/50732479

二、Android IPC方法

Android中可以使用的IPC方法有很多,主要如下:

1. 使用Bundle

Activity,Service,Receiver都是支持在Intent中传递Bundle的,由于Bundle实现了Parcelable接口,所以他可以在不同进程间传输。我们可以在Bundle中附加数据,并通过Intent传送出去。当然,传送的数据必须是能够被序列化的。

2. 使用共享文件

A进程把数据写入文件,B进程通过读取这个文件来获得数据。但这这种方法有一个问题就是并发读/写问题。有一个特例,SharedPreferences是Android中提供的轻量级存储方案,底层采用XML实现。但是系统对它的读写会基于缓存,也就是说再多进程模式下就变得不可靠了,有很大几率丢失数据。

3. Messager

用于可存放在message中的数据的传递
使用这个方式可以在不同进程间传递message对象这是一种轻量级的IPC方案,当传递的对象可以放入message中时可以考虑用这种方式,但是msg.object最好不要放因为不一定可以序列化 ;

4. AIDL

要用于调用远程服务的方法的情况 还可以注册接口 ;

5. ContentProvider

实现对另一个应用进程开放provider数据的查询, 底层是对Binder的封装 使之可以实现进程间通信 ;

6. Socket

功能强大 可以通过网络传输字节流 支持一对多并发操作 但是实现起来比较麻烦 不支持直接的RPC 常用于网络数据交换

以上方法中,Message,ContentProvider与AIDL的实现都使用到android的binder机制。

总结起来
当仅仅是跨进程的四大组件间的传递数据时 使用Bundle就可以 简单方便
当要共享一个应用程序的内部数据的时候 使用ContentProvider实现比较方便
当并发程度不高 也就是偶尔访问一次那种 进程间通信 用Messenger就可以
当设计网络数据的共享时 使用socket
当需求比较复杂 高并发 并且还要求实时通信 而且有RPC需求时 就得使用AIDL了
文件共享的方法用于一些缓存共享 之类的功能

三、Android IPC重要机制-Binder

1. Binder使用C/S通信架构:

这里写图片描述
1. 从上图可以看出client通过获得的server代理接口,对server进行直接调用;
2. 代理接口中定义的方法与server中定义的方法是一一对应的,client调用某个代理接口中的方法时,代理接口的方法会将client传递的参数打包成为Parcel对象,代理接口将该Parcel发送给内核中的binder driver.server会读取binder driver中的请求数据,如果是发送给自己的,解包Parcel对象,处理并将结果返回;
3. 整个的调用过程是一个同步过程,在server处理的时候,client会block住。因此如果在主线程中调用的service长时间不反回结果的话可能会导致anr。

2. Binder中主要参与者

binder的主要框架如下:
这里写图片描述

从上图中绘制出大概的框架,servicemanager是跨进程通信的服务主管,服务端提供服务前需要向servicemananger注册才能提供服务;客户端需要跨进程与服务端通信时,需要经过servicemanager进行查询并获得服务端端代理使用服务功能;
主要参与者有:
Client
Server
Service Manager
Binder Driver

3. Binder设计缘由

下面简析下为何这么设计:

1. 不同进程需要通过binder驱动来通信

Client和Server在不同进程中,当Client希望使用Server时,由于进程的隔离性 Client所在的ProcessA是不能读写Service所在的ProcessB中的内容,但系统内核可以,而Binder驱动就是运行在内核态。Binder驱动帮我们中转请求即可:
这里写图片描述

2. binder机制中的代理

在binder机制中client与server都不会直接与binder驱动打交道,binder机制中使用代理模式,client与server都只需要与相应的代理沟通即可,使Client及Server更专注于自身的功能实现,与Binder驱动打交道的任务交给代理去实现;
这里写图片描述

3. aidl

如果要自己实现Client端和Service端,通过上面的方式,虽然逻辑上独立出来了两个代理(客户端代理的Proxy、服务端的代理Stub),这两个代理还不是要自己实现?如果还是要自己实现,那分出来又有实际的意义?
AndroidSDK为我们提供了一个AIDL工具。我们只要新建一个AIDL文件,像创建普通interface一样(略有不同)在里面定义接口方法。定义好之后,androidSDK会根据aidl里面的接口定义,自动为我们生成一个java文件,其中就包括客户端代理Proxy和服务端代理Stub,并且自动生成了与Binder驱动通信的代码。
之所以将客户端代理叫做Proxy,服务端代理叫做Stub,就是因为aidl自动生成的代理中,两个代理的类名就是Proxy和Stub。我们在做的实际工作就只有真正的服务功能逻辑了。

4. 系统服务中的XXXManager

对于Andriod中的系统服务,我们在应用中使用XXXManager去使用服务,XXXManager中封装好了对应服务中的方法,实际manager内部还是通过客户端代理与binder驱动打交道来跟运行在另一个进程中的XXXService来通信,但对于Client来说,完全不知道,使得在Client跨进程调用服务的使用方法更简单,Client更专注于自身功能实现,满足单一职责原则。XXXManager是运行在Client进程中的。

5. ServiceManager

ServiceManager是binder机制中重要的角色,是所有服务的的管家,任何service在被使用之前,均要向SM(Service Manager)注册,同时客户端需要访问某个service时,应该首先向SM查询是否存在该服务。如果SM存在这个service,那么会将该service的handle返回给client,handle是每个service的唯一标识符。下面的文章中将对ServiceManager进行深入的分析。

四、总结

到这里,我们仍有很多疑问,比如系统中的服务很多,这些服务是如何管理的?Client是如何通过binder驱动精确找到自己需要的server端的?binder驱动是如何实现的?带着问题我们将在下面的几篇中详细阐述,以增加自己对binder机制的深入理解。
1. Binder(2)-ServiceManager服务
2. Binder(3)-Binder Driver的实现原理
3. Binder(4)-举例分析服务端注册及客户端调用服务流程

参考博客:
Android Binder机制介绍
http://www.cnblogs.com/zc9527/p/5638688.html
Android进程间通信(IPC)机制Binder简要介绍和学习计划
http://blog.csdn.net/luoshengyang/article/details/6618363/
Android中实现IPC的几种方式详细分析及比较
http://blog.csdn.net/u012760183/article/details/51397014

0 0