1.Binder通信机制介绍

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

1.1 Android与Linux通信机制的比較

尽管Android继承使用Linux的内核,但Linux与Android的通信机制不同。

在Linux中使用的IPC通信机制例如以下:

  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:是一个通用接口,导致其传输效率低,开销大;
    • 管道和消息队列:由于採用存储转发方式,所以至少须要拷贝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作为守护进程,处理client请求,管理全部服务项。

为了方便理解,我们能够把SM理解成DNSserver; 那么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的通信就有非常高的隐私性和安全性。

这样,整个Binder的通信流程就介绍完成了,可是对于详细的代码实现(比方binder_transaction_data是什么?binder_write_read.write_buffer又是什么?详细的驱动和逻辑实现又是怎么样?),在后面章节中会一一介绍。

几点疑问:

1. 是谁,怎么样成为SM守护进程,handle为0的binder实体什么时候创建?

2.  binder引用和实体是怎样创建的?在驱动中怎样实现的通信?

3. 在SM中,binder实体是如何转换成为引用的?

4. Server是怎样注冊服务,Client是怎样获取服务的?

读完兴许文章就会知道答案了!

Binder机制1---Binder原理介绍的更多相关文章

  1. 阿里面试官:Android中binder机制的实现原理及过程?

    Binder 是 Android 系统中非常重要的组成部分.Android 系统中的许多功能建立在 Binder 机制之上.在这篇文章中,我们会对 Android 中的 Binder 在系统架构中的作 ...

  2. Android Binder机制(一) Binder的设计和框架

    这是关于Android中Binder机制的一系列纯技术贴.花了一个多礼拜的时间,才终于将其整理完毕.行文于此,以做记录:也是将自己所得与大家分享.和以往一样,介绍Binder时,先讲解框架,然后再从设 ...

  3. 了解Binder机制原理和底层实现

    参考:http://www.2cto.com/kf/201606/515548.html 1.Binder通信机制介绍 这篇文章会先对比Binder机制与Linux的通信机制的差别,了解为什么Andr ...

  4. 理解 Android Binder 机制(一):驱动篇

    Binder的实现是比较复杂的,想要完全弄明白是怎么一回事,并不是一件容易的事情. 这里面牵涉到好几个层次,每一层都有一些模块和机制需要理解.这部分内容预计会分为三篇文章来讲解.本文是第一篇,首先会对 ...

  5. Android 进阶8:进程通信之 Binder 机制浅析

    读完本文你将了解: IBinder Binder Binder 通信机制 Binder 驱动 Service Manager Binder 机制跨进程通信流程 Binder 机制的优点 总结 Than ...

  6. 进程间通信方式与Binder机制原理

    1, Intent隐式意图携带数据 2, AIDL(Binder) 3, 广播BroadCast 4, 内容提供者ContentProvider --------------------------- ...

  7. Android Binder机制原理(史上最强理解,没有之一)(转)

    原文地址: http://blog.csdn.net/universus/article/details/6211589 Binder是Android系统进程间通信(IPC)方式之一.Linux已经拥 ...

  8. 进程间通信IPC与Binder机制原理

    1, Intent隐式意图携带数据 2, AIDL(Binder) 3, 广播BroadCast 4, 内容提供者ContentProvider 5,Messager(内部通过binder实现) 6, ...

  9. Android Binder机制介绍

    做过Android开发的同学可能有些体会,入门初期,工作内容主要是实现各式各样的UI界面,以及实现应用的业务逻辑.在这个阶段,我们会逐渐熟悉View系统,逐渐学会实现各种各样的界面以及动画效果.再往后 ...

随机推荐

  1. SQL删除数据库里所有表的外键,同时删除所有用户表

    SQL删除数据库里所有表的外键,同时删除所有用户表 删除所有的用户表的外键,直接将下面的代码拷贝到数据库里执行即可: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...

  2. cannot conform to protocol 的一点事

    学习UITableView过程中,回想视频打一遍代码,发现卡在了第一步.一直显示无法继承协议,而且还多了一个错误:definition conflicts with previous value.百度 ...

  3. LeetCode题解——Roman to Integer

    题目: 将罗马数字转换为整数. 解法: 可以参考上一篇数字转换为罗马数字的规则. 代码: class Solution { public: int sym2int(char sym) //罗马数字字符 ...

  4. ASP.NET MVC中的Json Binding和Validate

    引子:电子商务网站支付功能页面往往会有很多信息,对于这些信息的保存,往往是分步完成的,那么使用Ajax最合适不过了,比如其中的收货人信息模块.这些信息的新建和编辑保存都是用Ajax来完成的.那么有几种 ...

  5. (转载)OC学习篇之---类的初始化方法和点语法的使用

    昨天介绍了OC中类的定义和使用,今天我们来继续学习类的初始化方法和点语法的使用. 一.首先来看一下类的初始化方法 在Java中我们知道一个每个类都有构造方法,这里的初始化方法就是和构造方法一个概念的, ...

  6. Some_sort_algorithms

    复习下数据结构常用的排序算法,更多内容上wiki 快速排序(不稳定 O(n log n)) 快速排序(Quicksort)是对冒泡排序的一种改进.由C. A. R. Hoare在1962年提出.它的基 ...

  7. <Chapter 2>2-1.安装SDK

    开发一个应用需要的所有工具都包含在App Engine SDK中.对于Java和Python有不同的SDKs,每个都有特性对于用那种语言开发是有益的.SDKs在任何平台上工作,包括Windows,Ma ...

  8. 使用Async同步执行异步函数

    为了适应异步编程,减少回调的嵌套,我在项目中引入了Async,当批量处理且需要同步执行一些逻辑相同的异步函数时,觉得还是Async最为靠谱. 我有一个类似下面代码的场景,依据数组中的每一个元素执行一个 ...

  9. Junit3.8

    使用Junit的最佳实践:新建一个名为test的source folder,用于存放测试类源代码目标类与测试类应该位于同一个包下面,这样测试类中就不必导入源代码所在的包,因为他们位于同一个包下面 测试 ...

  10. C++问题-UniqueAppObject.cpp(147): error C3861: “GUXClientInit”: 找不到标识符

    问题经过:在同事的产品上增加新功能,拿来的代码包,用VS打开后,提示某个文件不存在,从项目中移除.CPP.H文件后,提示错误,提示如下:1>UniqueAppObject.cpp(147): e ...