Android 的 Binder 机制概念介绍

  结合了如下两篇文章的介绍,对Android 的 Binder 机制概念开始有了必定的理解。分享给你们。

-------------------------------------分割线---------------------------------

摘要

Binder是android 中一个很重要且很复杂的概念,它在系统的总体运做中发挥着极其重要的做用,不过本文并不打算从深层次分析Binder机制,有两点缘由:1是目前网上已经 有2篇很好的文章了,2是对Binder机制进行深刻底层乃至驱动的分析这一过程至关困难且至关耗时,所以并不适合重复造轮子。本文的角度是对 Android的Binder机制从总体和概念上进行分析,可以让你们很快明白到底什么是Binder,Binder是干什么的,Binder和应用开发 的关系是什么,总之,这篇文章仍是很值得去看一看的。

什么是Binder

1. 直观来讲,Binder是Android中的一个类,它继承了IBinder接口

2. 从IPC角度来讲,Binder是Android中的一种跨进程通讯方式,Binder还能够理解为一种虚拟的物理设备,它的设备驱动是/dev/binder,该通讯方式在linux中没有

3. 从Android Framework角度来讲,Binder是ServiceManager链接各类Manager(ActivityManager、WindowManager,etc)和相应ManagerService的桥梁

4. 从Android应用层来讲,Binder是客户端和服务端进行通讯的媒介,当你bindService的时候,服务端会返回一个包含了服务端业务调用的 Binder对象,经过这个Binder对象,客户端就能够获取服务端提供的服务或者数据,这里的服务包括普通服务和基于AIDL的服务

为何Android内核要使用Binder

Android中有大量的CS(Client-Server)应用方式,这就要求Android内部提供IPC方法,而linux所支持的进程通讯方式有两个问题:性能和安全性。

目 前linux支持的IPC包括传统的管道,System V IPC(消息队列/共享内存/信号量),以及socket,但只有socket支持Client-Server的通讯方式,因为socket是一套通用的 网络通讯方式,其传输效率低下切有很大的开销,好比socket的链接创建过程和中断链接过程都是有必定开销的。消息队列和管道采用存储-转发方式,即数 据先从发送方缓存区拷贝到内核开辟的缓存区中,而后再从内核缓存区拷贝到接收方缓存区,至少有两次拷贝过程。共享内存虽然无需拷贝,但控制复杂,难以使 用。

在安全性方 面,Android做为一个开放式,拥有众多开发者的的平台,应用程序的来源普遍,确保智能终端的安全是很是重要的。终端用户不但愿从网上下载的程序在不 知情的状况下偷窥隐私数据,链接无线网络,长期操做底层设备致使电池很快耗尽等等。传统IPC没有任何安全措施,彻底依赖上层协议来确保。首先传统IPC 的接收方没法得到对方进程可靠的UID/PID(用户ID/进程ID),从而没法鉴别对方身份。Android为每一个安装好的应用程序分配了本身的 UID,故进程的UID是鉴别进程身份的重要标志。使用传统IPC只能由用户在数据包里填入UID/PID,但这样不可靠,容易被恶意程序利用。可靠的身 份标记只有由IPC机制自己在内核中添加。其次传统IPC访问接入点是开放的,没法创建私有通道。好比命名管道的名称,system V的键值,socket的ip地址或文件名都是开放的,只要知道这些接入点的程序均可以和对端创建链接,无论怎样都没法阻止恶意程序经过猜想接收方地址获 得链接。

基于以上原 因,Android须要创建一套新的IPC机制来知足系统对通讯方式,传输性能和安全性的要求,这就是Binder。Binder基于 Client-Server通讯模式,传输过程只需一次拷贝,为发送发添加UID/PID身份,既支持实名Binder也支持匿名Binder,安全性 高。下图为Binder通讯过程示例:


http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1222/2204.html

---------------------分割线----------------------------


1.Binder通讯机制介绍

这篇文章会先对比Binder机制与Linux的通讯机制的差异,了解为何Android会另起炉灶,采用Binder。接着,会根据 Binder的机制,去理解什么是Service  Manager,在C/S模型中扮演什么角色。最后,会从一次完整的通讯活动中,去理解Binder通讯的过程。 html

1.1 Android与Linux通讯机制的比较

虽然Android继承使用Linux的内核,但Linux与Android的通讯机制不一样。 linux

在Linux中使用的IPC通讯机制以下: android

  1. 传统IPC:无名pipe, signal, trace, 有名管道 缓存

  2. AT&T Unix 系统V:共享内存,信号灯,消息队列 安全

  3. BSD Unix:Socket 服务器

而在Android中,并无使用这些,取而代之的是Binder机制。Binder机制是采用OpenBinder演化而来,在Android中使用它的缘由以下: 网络

  1. 采用C/S的通讯模式。而在linux通讯机制中,目前只有socket支持C/S的通讯模式,但socket有其劣势,具体参看第二条。 框架

  2. 有更好的传输性能。对比于Linux的通讯机制, socket

    • socket:是一个通用接口,致使其传输效率低,开销大; 性能

    • 管道和消息队列:由于采用存储转发方式,因此至少须要拷贝2次数据,效率低;

    • 共享内存:虽然在传输时没有拷贝数据,但其控制机制复杂(好比跨进程通讯时,需获取对方进程的pid,得多种机制协同操做)。

  3. 安全性更高。Linux的IPC机制在自己的实现中,并无安全措施,得依赖上层协议来进行安全控制。而Binder机制的 UID/PID是由Binder机制自己在内核空间添加身份标识,安全性高;而且Binder能够创建私有通道,这是linux的通讯机制所没法实现的 (Linux访问的接入点是开放的)。

综上所述,Android采用Binder机制是有道理的。既然Binder机制这么多优势,那么咱们接下来看看它是怎样经过C/S模型来实现的。

1.2 Binder在Service服务中的做用

在android中,有不少Service都是经过binder来通讯的,好比MediaServer旗下包含了众多service:

  •     AudioFlinger 音频核心服务

  •     AudioPolicyService:音频策略相关的重要服务

  •     MediaPlayerService:多媒体系统中的重要服务

  •     CameraService:有关摄像/照相的重要服务

Binder在C/S中的流程以下:

  1. Server注册服务。Server做为众多Service的拥有者,当它想向Client提供服务时,得先去Service Manager(之后缩写成SM)那儿注册本身的服务。Server能够向SM注册一个或多个服务。

  2. Client申请服务。Client做为Service的使用者,当它想使用服务时,得向SM申请本身所须要的服务。Client能够申请一个或多个服务。

  3. 当Client申请服务成功后,Client就可使用服务了。

SM一方面管理Server所提供的服务,同时又响应Client的请求并为之分配相应的服务。扮演的角色至关于月老,两边牵线。这种通讯方式的好处是: 一方面,service和Client请求便于管理,另外一方面在应用程序开发时,只需为Client创建到Server的链接,就可花不多时间和精力去实 现Server相应功能。那么,Binder与这个通讯模式有什么关系呢?!其实,3者的通讯方式就是Binder机制(例如:Server向SM注册服 务,使用Binder通讯;Client申请请求,用的是Binder通信)

1.3 Binder通讯机制流程(总体框架)

上图便是Binder的通讯模型。咱们能够发现:

  1. Client和Server是存在于用户空间

  2. Client与Server通讯的实现,是由Binder驱动在内核空间实现

  3. SM做为守护进程,处理客户端请求,管理全部服务项。

为了方便理解,咱们能够把SM理解成DNS服务器; 那么Binder Driver 就至关于路由的功能。这里就涉及到Client和Server是如何通讯的问题。下面对1.2中提到的3个流程进行说明。

1.3.1 Server向SM注册服务

  1. 首先,XXXServer(XXX表明某个)在本身的进程中向Binder驱动申请建立一个XXXService的Binder的实体,

  2. Binder驱动为这个XXXService建立位于内核中的Binder实体节点以及Binder的引用,注意,是将名字和新建的引用打包传递给SM(实体没有传给SM),通知SM注册一个名叫XXX的Service。

  3. SM收到数据包后,从中取出XXXService名字和引用,填入一张查找表中。

  4. 此时,若是有Client向SM发送申请服务XXXService的请求,那么SM就能够在查找表中找到该Service的Binder引用,并把Binder引用(XXXBpBinder)返回给Client。

在进一步了解Binder通讯机制以前,咱们先弄清几个概念。

  1. 引用和实体。这里,对于一个用于通讯的实体(能够理解成具备真实空间的Object),能够有多个该实体的引用(没有真实空间,能够理解成实体的 一个连接,操做引用就会操做对应连接上的实体)。若是一个进程持有某个实体,其余进程也想操做该实体,最高效的作法是去得到该实体的引用,再去操做这个引 用。

  2. 有些资料把实体称为本地对象,引用成为远程对象。能够这么理解:引用是从本地进程发送给其余进程来操做实体之用,因此有本地和远程对象之名。

1.3.2 一个问题-如何得到SM的远程接口

若是你足够细心,会发现这里有一个问题:

Sm和Server都是进程,Server向SM注册Binder须要进程间通讯,当前实现的是进程间通讯却又用到进程间通讯。这就比如鸡生蛋、蛋生鸡,但至少得先有其中之一。

巧妙的Binder解决思路:

针对Binder的通讯机制,Server端拥有的是Binder的实体;Client端拥有的是Binder的引用。
若是把SM看做Server端,让它在Binder驱动一运行起来时就有本身的Binder实体(代码中设置ServiceManager的Binder 其handle值恒为0)。这个Binder实体没有名字也不须要注册,全部的client都认为handle值为0的binder引用是用来与SM通讯 的(代码中是这么实现的),那么这个问题就解决了。那么,Client和Server中这么达成协议了(handle值为0的引用是专门与SM通讯之用 的),还不行,还须要让SM有handle值为0的实体才算大功告成。怎么实现的呢?!当一个进程调用Binder驱动时,使用 BINDER_SET_CONTEXT_MGR命令(在驱动的binder_ioctl中)将本身注册成SM时,Binder驱动会自动为它建立 Binder实体。这个Binder的引用对全部的Client都为0。


1.3.3 Client从SM得到Service的远程接口


Server向SM注册了Binder实体及其名字后,Client就能够经过Service的名字在SM的查找表中得到该Binder的引用了 (BpBinder)。Client也利用保留的handle值为0的引用向SM请求访问某个Service:我申请访问XXXService的引用。 SM就会从请求数据包中得到XXXService的名字,在查找表中找到该名字对应的条目,取出Binder的引用打包回复给client。之 后,Client就能够利用XXXService的引用使用XXXService的服务了。
若是有更多的Client请求该Service,系统中就会有更多的Client得到这个引用。

1.3.4 创建C/S通路后

首先要理清一个概念:client拥有本身Binder的实体,以及Server的Binder的引用;Server拥有本身Binder的实体,以及Client的Binder的引用。咱们也能够从接收方和发送方的方式来理解:

  • 从client向Server发数据:Client为发送方,拥有Binder的实体;Server为接收方,拥有Binder的引用

  • 从server向client发数据:Server为发送方,拥有Binder的实体;client为接收方,拥有Binder的引用。

也就是说,咱们在创建了C/S通路后,无需考虑谁是Client谁是Server,只要理清谁是发送方谁是接收方,就能知道Binder的实体和引用在哪边。


创建CS通路后的流程:(当接收方得到Binder的实体,发送方得到Binder的引用后)

  1. 发送方会经过Binder实体请求发送操做。

  2. Binder驱动会处理这个操做请求,把发送方的数据放入写缓存(binder_write_read.write_buffer) (对于接收方为读缓冲区),并把read_size(接收方读数据)置为数据大小(对于具体的实现后面会介绍);

  3. 接收方以前一直在阻塞状态中,当写缓存中有数据,则会读取数据,执行命令操做

  4. 接收方执行完后,会把返回结果一样用binder_transaction_data结构体封装,写入写缓冲区(对于发送方,为读缓冲区)

1.3.5 匿名Binder

以前在介绍Android使用Binder机制的优势中,提到Binder能够创建点对点的私有通道,匿名Binder就是这种方式。在 Binder通讯中,并非全部用来通讯的Binder实体都须要注册给SM广而告之的,Server能够经过已创建的实体Binder链接将建立的 Binder实体传给Client。而这个Binder没有向SM注册名字。这样Server与Client的通讯就有很高的隐私性和安全性。

http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0319/2619.html

相关文章
相关标签/搜索