做过Android开发的同学可能有些体会,入门初期,工作内容主要是实现各式各样的UI界面,以及实现应用的业务逻辑。在这个阶段,我们会逐渐熟悉View系统,逐渐学会实现各种各样的界面以及动画效果。再往后,当我们想更深入的学习android系统,比如学习android四大组件的启动过程、AMS、PMS等等时,都会遇到一个叫做Binder的东西。结合笔者的经验,Binder可以说是深入理解Android系统的重要基础。binder作为android系统进程间通信的机制,贯穿在方方面面。我们平时使用最多的startActivity、startService都是通过binder机制与AMS所在进程进行通信。本文主要对Binder机制的体系结构作简要介绍,相信读者看完后,会对binder有一个总体上的理解与把握。

注:笔者初学binder时,曾经看过一些binder介绍的文章,并且过早的纠结于一些文章中的binder代码细节,感觉非常吃力。本文仅从宏观上对binder机制进行介绍。相信读者先理解了binder的总体结构后,再去深入细节,学习效果会更好。

Binder是什么、能做什么?

Binder是android系统里面的进程间通信机制。androd系统中,不同的app运行在不同的进程中,同一个app的不同组件也可能运行在不同的进程中(androidManifest文件中android:process)。当一个进程想为其它进程提供服务时,就需要通过进程间通信的方式来提供服务。打个比方:我们有一个APP1,里面有个service组件可以提供计算器的服务。当另外一个APP2也想使用APP1里面的service的计算器的服务时,由于不同的APP运行在不同的进程中,所以,APP2是无法直接使用APP1里面的service。由于跨越了进程,只能通过进程间通信机制来完成。

再说的形象点,APP1所在进程有一个对象object1,其中有一个方法method1。 APP2所在的另外一个进程,想使用object1的method1方法。binder可能帮助我们在APP2所在进程拿到一个object1对象的引用,使我们能够像调用本地对象一样,通过object1.method1()直接调用。利用binder,我们可以突破进程的限制,将对象传给其它进程,让其它进程方便调用对象的方法。

为什么用Binder?

理解了binder是什么、能做什么后,大家可能会有疑问:android系统基于Linux,linux本身具有很多的进程间通信方式可供选择,为什么android不使用linux自带的一个进程间通信方式,而新创造了一个binder?是重复造轮子吗?

Linux自带的进程间通信方式有:文件、signal、socket、Pipe、共享内存...,  为什么使用Binder?笔者总结原因有两大方面:

1 历史原因。Binder最早并不是为Android系统而设计的,最开始有一个OpenBinder的东西,用在一个叫做Palm Cobaltw的为内核操作系统上。后来,Palm Cobaltw移植到了Linux系统上,OpenBinder也跟着移植了过来。Google在组建Android开发团队的时候,聘请了一位叫做Dianne Hackborn的工程师,而他就是OpenBinder的核心人员。后面在做android进程间通信时,发现binder很合适,就理所当然的在android系统上使用了Binder。

2 binder自身的一些特点和优势。Binder实现进程间通信时,在安全性和效率方面,都很合适用在android系统中。关于这点,先有个印象即可。

Binder有哪些组成部分?

一个Binder系统由四部分组成:Binder客户端、Binder服务端、Binder驱动、服务登记查询模块

Binder客户端:想要使用服务的进程

Binder服务端:实际提供服务的进程

Binder驱动:我们在客户端先通过Binder拿到一个服务端进程中的一个对象的引用,通过这个引用,直接调用对象的方法获取结果。在这个引用对象执行方法时,它是先将方法调用的请求传给binder驱动;然后binder驱动再将请求传给服务端进程;服务端进程收到请求后,调用服务端“真正”的对象来执行所调用的方法;得出结果后,将结果发给binder驱动;binder驱动再将结果发给我们的客户端;最终,我们在客户端进程的调用就有了返回值。Binder驱动,相当于一个中转者的角色。通过这个中转者的帮忙,我们就可以调用其它进程中的对象。

服务登记查询模块:我们调用其它进程里面的对象时,首先要获取这个对象。这个对象其实代表了另外一个进程能给我们提供什么样的服务(再直接一点,就是:对象中有哪些方法可以让客户端进程调用)。首先服务端进程要在某个地方注册登记一下,告诉系统我有个对象可以公开给其它进程来提供服务。当客户端进程需要这个服务时,就去这个登记的地方通过查询来找到这个对象。

Binder各部分是如何工作的?

下面从客户端进程的角度来看看binder的工作机制

作为客户端进程,仅仅是想使用服务端进程提供的服务而已:
 
但是由于进程的隔离性,Client所在的ProcessA是不能读写Service所在的ProcessB中的内容,但系统内核可以,而Binder驱动就是运行在内核态。Binder驱动帮我们中转请求即可:
 
有了Binder驱动后,对于Client端和Service端,需要额外专门与Binder驱动打交道,为了帮Client和Service端屏蔽掉与Binder驱动打交道这件很low的工作,我们可以分别为Client和Service设计一个代理,让他们只与代理打交道即可,将与Binder驱动打交道的任务放在代理里面:
读者可能要问,如果要自己实现Client端和Service端,通过上面的方式,虽然逻辑上独立出来了两个代理(客户端代理的Proxy、服务端的代理Stub),这两个代理还不是要自己实现?如果还是要自己实现,那分出来又有实际的意义?
AndroidSDK为我们提供了一个AIDL工具。我们只要新建一个AIDL文件,像创建普通interface一样(略有不同)在里面定义接口方法。定义好之后,androidSDK会根据aidl里面的接口定义,自动为我们生成一个java文件,其中就包括客户端代理Proxy和服务端代理Stub,并且自动生成了与Binder驱动通信的代码,是不是很爽。上面的图片中,之所以将客户端代理叫做Proxy,服务端代理叫做Stub,就是因为aidl自动生成的代理中,两个代理的类名就是Proxy和Stub。我们在做的实际工作就只有真正的服务功能逻辑了。
 
再更近一步的想想,对于客户端而言,更理想的状态是,客户端完全不用知道调用的对象是一个本地对象,还是一个服务端进程中的对象。按照上面的图片,客户端显然知道自己调用的是远程对象,所以通过一个Proxy来调。我们在开发android应用程序的过程中,都会用到一些系统提供的XXXManager(ActivityManager、PackageManager、WifiManager、PowerManager等等),而这些manager所要实现的目的之一,正是帮Client屏蔽掉Binder的实现细节。有了这些Manager,Client在使用时,首先通过getServiceManager(xxx)获取一个manager对象,后面就直接调用manager中封装好的服务方法即可。这样以来,manager内部实际上还是通过客户端代理,通过binder驱动来跟运行在另外一个进程中的xxxService来通信,但对于Client来说,完全不用知道。如下图:
对于一些系统服务,ActivityManager、PackagerManager等等,不光为Client屏幕了Binder相关细节,还可以对真正的服务端对象提供的服务API进行过滤和控制,可以只为Client暴露一个服务API的子集。
 
最后一个疑问:到上面的图片所讲的内容为止,前提条件是Client先获取到了一个Proxy或者Manager,然后才完成后面的进程间通信。那到底Client是如何获取到Manager或者Proxy呢?
首先以一些系统服务为例:
前面提到,Binder机制的四个组成部分中,有一个是“服务登记查询模块”,对应上图中的Context Manager,在Android系统中运行时的进程名为:servicemanager。在所有服务进程中,servicemanager第一个启动,原因也不难理解,如果其它服务进程先于servicemanager启动,到哪里去注册?
 
如上图所示,假设Service所在的进程ProcessB在servicemanager进程启动后启动,ProcessB需要向servicemanager注册。“注册”这个动作,本质也是要跨进程通信,从ProcessB到servicemanager,这时,Service成为了本次跨进程通信的客户端,ContextManager成为了服务端。客户端到服务端的通信,按前面讲到的内容,需要一个Proxy或者Manager。这个Proxy或者Manager从哪里获取呢?问题好像陷入了循环死锁?因为ContextManager的特殊地位,读者可以理解为系统对它有点特殊待遇,Service可以从一个全局固定的地方直接去拿Proxy或者Manager,而不用像Client那样通过查询来获取Proxy/Manager。拿到了客户端代理,具体注册的通信过程如上文所讲,不再重复。到这里为止,Service就成功注册到了ContextManager中。
 
客户端Client初始化Manager时,manager也像刚才的Service,直接从某个固定的地方拿到ContextManager的代理,通过代理,去查询ContextManager,获取一个“提供所要服务的代理对象”。manager有了这个对象,Client就可以通过manager来使用服务了,调用逻辑如图:
 
当自己来实现Client和Service时,Client如何获取Proxy代理对象?
先讲一下实现方式:一般我们会在App中通过Service组件的方式来创建一个服务。其它App通过BindService的方式连接到Service,通过onServiceConnected回调就能获取Proxy代理对象。具体实现可参考:http://blog.csdn.net/singwhatiwanna/article/details/17041691
 

总结

本文简要介绍了Binder跨进程通信机制的逻辑,希望能帮助初学Binder的同学快速入门,提交学习效率。文中使用的图片以及讲解思路,来自于这个文档:

http://events.linuxfoundation.org/images/stories/slides/abs2013_gargentas.pdf,加进去一些笔者自己的思考和总结。一些地方如果有错误,欢迎指正交流。

另外推荐一篇binder入门的文章:http://weishu.me/2016/01/12/binder-index-for-newer/

Android Binder机制介绍的更多相关文章

  1. android binder机制之——(创建binder服务)

      Binder机制编程 前面的几篇文章具体介绍了android中binder机制的方方面面,相信你对binder机制已经有了较深刻的理解.俗话说得好"学以致用",以下我们就通过在 ...

  2. 【转】Android - Binder机制

    以下几篇文章是分析binder机制里讲得还算清楚的 目录 1. Android - Binder机制 - ServiceManager 2. Android - Binder机制 - 普通servic ...

  3. Android Binder机制彻底梳理二

    根据AIDL了解整体调用流程[重点分析AIDL流程]: 在上一次https://www.cnblogs.com/webor2006/p/11741743.html中我们已经对Android Binde ...

  4. Android Binder机制简单了解

    Binder -- 一种进程间通信(IPC)机制, 基于OpenBinder来实现 毫无疑问, 老罗的文章是不得不看的 Android进程间通信(IPC)机制Binder简要介绍和学习计划 浅谈Ser ...

  5. ANDROID BINDER机制浅析

    Binder是Android上一种IPC机制,重要且较难理解.由于Linux上标准IPC在灵活和可靠性存在一定不足,Google基于OpenBinder的设计和构想实现了Binder. 本文只简单介绍 ...

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

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

  7. Android Binder机制彻底梳理一

    Binder架构图: 先来瞅一下它的整体架构图: 其中粉红部分是上层的Binder,而蓝色的则是下层的Binder,很显然上层的是依赖于下层的. 什么是Binder[有个大概了解]? 这里从几个层面来 ...

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

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

  9. 浅谈android binder机制

    binder机制 是谷歌优化在android上更适合终端的IPC(多进程通信方式),满足系统对通信方式,传输性能和安全性的要求. 特性: 1. 用驱动程序来推进进程间的通信.2. 通过共享内存来提高性 ...

随机推荐

  1. spring-boot-plus V1.4.0发布 集成用户角色权限部门管理

    RBAC用户角色权限 用户角色权限部门管理核心接口介绍 Shiro权限配置

  2. web.xml不同版本的头信息

    web.xml v2.3 <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web- ...

  3. 在windows主机中,利用XSHELL生成“密钥”进行虚拟机与物理机的传输

    首先你要有虚拟机,其次你要可以互相ping通(主机与虚拟机) 接着你要有xshell 软件  没有的话可以点击链接下载 Xshell  6  提取码:cj5t 打开Xshell软件  在工具栏中选择“ ...

  4. NOIP模拟 18

    这次时间分配不合理,沉迷大模拟无法自拔 虽然A了但是根本就没给T3留时间555 T3如果有时间看看数据范围应该可以想到QJ掉20分的555 T1 引子 打这题的时候感觉自己在做图像处理.. 然后调了各 ...

  5. 《吊打面试官》系列-Redis终章_凛冬将至、FPX_新王登基

    你知道的越多,你不知道的越多 点赞再看,养成习惯 前言 Redis在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在Redis的使用和原理方面对小伙伴们进行360°的刁难.作为一个在互联 ...

  6. 深入了解 Java Resource && Spring Resource

    在Java中,为了从相对路径读取文件,经常会使用的方法便是: xxx.class.getResource(); xxx.class.getClassLoader().getResource(); 在S ...

  7. 【Spdy协议简介】

    一.SPDY协议诞生记 SPDY (SPDY 是 Speedy 的昵音,意思是更快)是 Google 开发的基于传输控制协议 (TCP) 的应用层协议 ,那么为什么要搞一个SPDY出来呢?距离万维网之 ...

  8. CSP-S 94 (sb lsc gc赛)

    不要问我为什么题解倒着写,因为在填坑! 关于这场比赛就是我sb的再现 考完试旁边_LH叱的一声说道:“lsc真**垃圾”; lsc:........确实很垃圾! ------------------- ...

  9. Linux | 性能分析系列学习 (2)

    常分析方法: 1.监控大盘,是否异常报警 2..平均负载情况,(top    /    htop )平均负载体现的是系统的一个整体情况,他应该是cpu.内存.磁盘性能的一个综合,一般是平均负载的值大于 ...

  10. acm经验(转)

    先简单介绍一下自己: 高中在OI打过一段时间酱油,大一后暑假进入ACM集训队,到大三寒假,总共一年半的ACM生涯. 总共参加了四场比赛:区域赛一银(2013长春)一铜(2013杭州)一铁(2012金华 ...