IPC之binder机制
我们知道,在Android系统中,每一个应用程序都运行在独立的进程中,这也保证了当其中一个程序出现异常而不会影响另一个应用程序的正常运转。在许多情况下,我们activity都会与各种系统的service打交道,很显然,我们写的程序中activity与系统service肯定不是同一个进程,但是它们之间是怎样实现通信的呢?Binder是android中一种实现进程间通信(IPC)的方式之一。
了解Binder
1.binder用来做什么?用来实现不同进程之间的通信。
2.Binder是什么?binder属于一个驱动,工作在linux层面,运行在内核态,它的操作完成是基于一段内存。所以我们开发的程序中对binder的使用都是通过系统的调用来完成的。
3.binder是怎样实现进程通信的?我们来通过Binder的架构来了解它实现进程间通信(IPC)的过程。
1、Binder是基于OpenBinder,在Android系统上使用的进程间通信机制
Binder基于Client-Server通信模式,本质上可以理解为它实现了Client对Server对象的远程调用。比如,有某个binder对象A位于Server中,该对象提供了一套函数用以实现对服务的请求,而在一个或多个Client中包含对象A的引用,Client通过该引用可以调用远端Server中对象A的接口函数,这种远端调用对Client而言,与调用本地对象并无区别。
2、Binder架构由ServiceManager、服务端、binder驱动、客户端四个部分构成
其中Client、Service、Service Manager运行在用户空间,Binder驱动运行在内核空间。(用户空间、内核空间是内核缓冲区的两组成部分)
ServiceManager、Binder驱动由系统负责提供,Client和Service组件由应用程序来实现。
A、ServiceManager是一个守护进程,负责管理服务,即所有的Server需要向ServiceManager注册服务。同时,ServiceManager向Client提供查询和获取Server的接口。
B、服务器端。一个Binder服务器端就是一个Binder类的对象。当创建一个Binder对象后,内部就会开启一个线程,这个线程用于接收binder驱动发送的信息,收到消息后,会执行相关的服务代码。
具体做法是:1在服务器端先生成方法代理,2再通过覆写onbind方法返回一个IBinder对象(代理的实例)
private class MyAgent extends IService.Stub{ @Override public void callMethodInService() { methodInService(); } } @Override public IBinder onBind(Intent intent) { return new MyAgent(); }
Service
C、Binder驱动。当服务端成功创建一个Binder对象后,Binder驱动也会相应创建一个mRemote对象,该对象的类型也是Binder类。客户就可以借助这个mRemote对象来访问远程服务。
D、客户端。客户端要想访问Binder的远程服务,就必须获取远程服务的Binder对象在binder驱动层对应的mRemote引用。当获取到mRemote对象的引用后,就可以调用相应Binder对象的服务了。
具体做法:1通过获得ServiceConnection实例,在onServiceConnection方法中调用服务端binder代理对象,2再在客户端通过开启service配置远程服务action和连接类实例完成与远程服务端的连接,进而通过连接类达到调用服务端方法的目的
//绑定远程 服务 public void bindservice(View v){ Intent intent = new Intent(); intent.setAction("com.itheima.rms"); bindService(intent, new MyConnection(), BIND_AUTO_CREATE); } private IService agent; private class MyConnection implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder service) { // agent = (IService )service agent = IService.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { } }
Client
在这里,我们可以看到,客户端是通过Binder驱动来调用服务端的相关服务。1首先,在服务端创建一个Binder对象,2然后相应在Binder驱动中创建一个Binder对象,3接着客户端通过获取Binder驱动中Binder对象的引用来调用服务端的服务。在Binder机制中正是借着Binder驱动将不同进程间的组件bind(粘连)在一起,实现通信。
3、实现一个binder通信实例,需要经过以下步骤:
- 获得ServiceManager的对象引用
- 向ServiceManager注册新的Service
- 在Client中通过ServiceManager获得Service对象引用
- 在Client中发送请求,由Service返回结果。
4、客户端和服务端的通信可以视为两次通信:
第一次是客户端获取Binder驱动中创建的代理Binder对象引用;
第二次是客户端通过获取的代理Binder对象引用,调用服务端中的服务
5、为什么android选用Binder来实现进程间通信?
5.1 可靠性
在移动设备上,通常采用基于Client-Server的通信方式来实现互联网与设备间的内部通信。目前linux支持IPC包括传统的管道,System V IPC,即消息队列/共享内存/信号量,以及socket中只有socket支持Client-Server的通信方式。Android系统为开发者提供了丰富进程间通信的功能接口,媒体播放,传感器,无线传输。这些功能都由不同的server来管理。开发都只关心将自己应用程序的client与server的通信建立起来便可以使用这个服务。毫无疑问,如若在底层架设一套协议来实现Client-Server通信,增加了系统的复杂性。在资源有限的手机 上来实现这种复杂的环境,可靠性难以保证。
5.2 传输性能
- socket主要用于跨网络的进程间通信和本机上进程间的通信,但传输效率低,开销大。
- 消息队列和管道采用存储-转发方式,即数据先从发送方缓存区拷贝到内核开辟的一块缓存区中,然后从内核缓存区拷贝到接收方缓存区,其过程至少有两次拷贝。
- 共享内存虽然无需拷贝,但控制复杂。
比较各种IPC方式的数据拷贝次数。
- 共享内存:0次。
- Binder:1次。
- Socket/管道/消息队列:2次。
5.3 安全性
Android是一个开放式的平台,所以确保应用程序安全是很重要的。Android对每一个安装应用都分配了UID/PID,其中进程的UID是可用来鉴别进程身份。传统的只能由用户在数据包里填写UID/PID,这样不可靠,容易被恶意程序利用。而我们要求由内核来添加可靠的UID。
所以,出于可靠性、传输性、安全性。android建立了一套新的进程间通信方式。
6、ServiceManager 与实名Binder
和DNS类似,SMgr的作用是将字符形式的Binder名字转化成Client中对该Binder的引用,使得Client能够通过Binder名字获得对Server中Binder实体的引用。注册了名字的Binder叫实名Binder,就象每个网站除了有IP地址外还有自己的网址。Server创建了Binder实体,为其取一个字符形式,可读易记的名字,将这个Binder连同名字以数据包的形式通过Binder驱动发送给SMgr,通知SMgr注册一个名叫张三的Binder,它位于某个Server中。驱动为这个穿过进程边界的Binder创建位于内核中的实体节点以及SMgr对实体的引用,将名字及新建的引用打包传递给SMgr。SMgr收数据包后,从中取出名字和引用填入一张查找表中。
细心的读者可能会发现其中的蹊跷:SMgr是一个进程,Server是另一个进程,Server向SMgr注册Binder必然会涉及进程间通信。当前实现的是进程间通信却又要用到进程间通信,这就好象蛋可以孵出鸡前提却是要找只鸡来孵蛋。Binder的实现比较巧妙:预先创造一只鸡来孵蛋:SMgr和其它进程同样采用Binder通信,SMgr是Server端,有自己的Binder对象(实体),其它进程都是Client,需要通过这个Binder的引用来实现Binder的注册,查询和获取。SMgr提供的Binder比较特殊,它没有名字也不需要注册,当一个进程使用BINDER_SET_CONTEXT_MGR命令将自己注册成SMgr时Binder驱动会自动为它创建Binder实体(这就是那只预先造好的鸡)。其次这个Binder的引用在所有Client中都固定为0而无须通过其它手段获得。也就是说,一个Server若要向SMgr注册自己Binder就必需通过0这个引用号和SMgr的Binder通信。类比网络通信,0号引用就好比域名服务器的地址,你必须预先手工或动态配置好。要注意这里说的Client是相对SMgr而言的,一个应用程序可能是个提供服务的Server,但对SMgr来说它仍然是个Client。
7、Client 获得实名Binder的引用
Server向SMgr注册了Binder实体及其名字后,Client就可以通过名字获得该Binder的引用了。Client也利用保留的0号引用向SMgr请求访问某个Binder:我申请获得名字叫张三的Binder的引用。SMgr收到这个连接请求,从请求数据包里获得Binder的名字,在查找表里找到该名字对应的条目,从条目中取出Binder的引用,将该引用作为回复发送给发起请求的Client。从面向对象的角度,这个Binder对象现在有了两个引用:一个位于SMgr中,一个位于发起请求的Client中。如果接下来有更多的Client请求该Binder,系统中就会有更多的引用指向该Binder,就象java里一个对象存在多个引用一样。而且类似的这些指向Binder的引用是强类型,从而确保只要有引用Binder实体就不会被释放掉。通过以上过程可以看出,SMgr象个火车票代售点,收集了所有火车的车票,可以通过它购买到乘坐各趟火车的票-得到某个Binder的引用。
8、匿名 Binder
并不是所有Binder都需要注册给SMgr广而告之的。Server端可以通过已经建立的Binder连接将创建的Binder实体传给Client,当然这条已经建立的Binder连接必须是通过实名Binder实现。由于这个Binder没有向SMgr注册名字,所以是个匿名Binder。Client将会收到这个匿名Binder的引用,通过这个引用向位于Server中的实体发送请求。匿名Binder为通信双方建立一条私密通道,只要Server没有把匿名Binder发给别的进程,别的进程就无法通过穷举或猜测等任何方式获得该Binder的引用,向该Binder发送请求。
9、IBinder、BpBinder、BBinder
9.1 IBinder
Android对Binder机制进行了抽象,定义了IBinder接口,该接口是对跨进程对象的抽象,在C/C++和Java层都有定义。IBinder定义了一套使用Binder机制来实现客户端和服务端的通信协议。
一个普通对象只能在当前进程中被访问,若希望它被其他进程访问,就必须实现IBinder接口。IBinder接口可指向本地对象,也可指向远程对象,关键在于IBinder对象的transact函数。若IBinder指向一个服务端代理,那么transact只负责把请求发送给服务器;若IBinder指向一个服务端,那么transact只负责提供服务即可。因此,不论是服务端还是服务端代理对象,都必实现该接口,这样才能进行Binder通信
9.2 服务端代理对象BpBinder
BpBinder是服务端代理对象,即远程对象在当前进程的代理。实际上,它也是Binder通信存在于客户端的进程,实现了IBinder接口。
需要注意的是,transact方法是同步方法,将会挂起客户进程的当前线程,直到Service把请求处理完成并返回结果。
9.3 服务端BBinder
服务端同样需要实现IBinder接口(具体案例见Android技术内幕·系统卷3.3.2.3 P140)
10、Binder实体对象生命周期
- Client进程通过ServiceManager获得一个Service组件代理对象接口;
- Binder驱动程序会找到与该Service组件对应的Binder实体对象,再创建一个Binder引用对象来引用它;
- Client进程不再引用一个Service组件时,会请求Binder驱动程序释放之前为它创建的一个Binder引用对象
11、ServiceManager启动过程
- 调用函数binder_open打开设备文件/dev/binder,以及将它映射到本进程的地址空间;
- 调用函数binder_become_context_manager将自己注册为Binder进程间通信机制的上下文管理者;
- 调用函数binder_loop来循环等待和处理Client进程的通信请求
http://8599981.blog.51cto.com/8589981/1404229
http://blog.csdn.net/yueliangniao1/article/details/7188549
http://blog.csdn.net/coding_glacier/article/details/7520199
http://www.linuxidc.com/Linux/2012-07/66195.htm
http://blog.csdn.net/chaihuasong/article/details/10071903
Android系统源代码情景分析P145
IPC之binder机制的更多相关文章
- 进程间通信IPC与Binder机制原理
1, Intent隐式意图携带数据 2, AIDL(Binder) 3, 广播BroadCast 4, 内容提供者ContentProvider 5,Messager(内部通过binder实现) 6, ...
- 大型项目必备IPC之Binder机制原理(一)
阿里P7Android高级架构进阶视频免费学习请点击:https://space.bilibili.com/474380680 摘要 Binder是Android系统进程间通信(IPC)方式之一.Li ...
- Binder机制,从Java到C (1. IPC in Application Remote Service)
转载请标注:张小燕:http://www.cnblogs.com/zhangxinyan 1. Application 中的 service 我们知道Android中Service有三种类型:Loca ...
- Binder机制,从Java到C (2. IPC in System Service :AMS)
1.建立Activity和Service的IPC之前 在上一篇 Binder机制,从Java到C (1. IPC in Application Remote Service) 里面有说到Activi ...
- 深入理解Android IPC机制之Binder机制
Binder是Android系统进程间通信(IPC)方式之一.Linux已经拥有的进程间通信IPC手段包括(Internet Process Connection): 管道(Pipe).信号(Sign ...
- Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制?
目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...
- 【Android - IPC】之Binder机制简介
参考资料: 1.<Android开发艺术探索>第二章2.3.3 Binder 2.[Android Binder设计与实现-设计篇] 3.[Android Binder机制介绍] 1. 什 ...
- 浅谈android binder机制
binder机制 是谷歌优化在android上更适合终端的IPC(多进程通信方式),满足系统对通信方式,传输性能和安全性的要求. 特性: 1. 用驱动程序来推进进程间的通信.2. 通过共享内存来提高性 ...
- Android中的Binder机制的简要理解
转载自:http://www.linuxidc.com/Linux/2012-07/66195.htm http://blog.csdn.net/sunxingzhesunjinbiao/articl ...
随机推荐
- ios10适配
1: 去除打印多余的log信息: xcode-->Product-->Scheme-->edite Scheme 中在Ecvironment Variables 中添加OS_ACTI ...
- LARGE SCALE GAN TRAINING FOR HIGH FIDELITY NATURAL IMAGE SYNTHESIS
最强GAN图像生成器,真假难辨 论文地址: https://openreview.net/pdf?id=B1xsqj09Fm 更多样本地址: https://drive.google.com/driv ...
- Python + selenium + unittest装饰器 @classmethod
前言 前面讲到unittest里面setUp可以在每次执行用例前执行,这样有效的减少了代码量,但是有个弊端,比如打开浏览器操作,每次执行用例时候都会重新打开,这样就会浪费很多时间. 于是就想是不是可以 ...
- JavaScript中的垃圾回收和内存泄漏
摘要: JS内存管理. 作者:浪里行舟 Fundebug经授权转载,版权归原作者所有. 前言 程序的运行需要内存.只要程序提出要求,操作系统或者运行时就必须供给内存.所谓的内存泄漏简单来说是不再用到的 ...
- 使用Arduino Wire Library读取温湿度传感器AM2321
AM2321是采用I2C总线或单总线通讯的国产温湿度传感器.在AM2321手册中,当采用I2C通讯时,手册指定了多处需要主机等待的时间间隔,包括: (1)唤醒传感器时,从机不回复ACK,但主机主要等待 ...
- [Erlang32]ibrowse流程及性能测试
1.简介 ibrowse是用erlang写的一个HTTP client.github地址:https://github.com/cmullaparthi/ibrowse 使用方法见项目的readme. ...
- Tempdb--Snapshot
The insert operation does not cause a row version to be generated because there is really no prvious ...
- .NET中异常与错误码优劣势对比
.NET之所以选择异常,而不是返回错误码来报告异常,是由于前者有以下几个优势: 1.异常与oop语言的结合性更好.oop语言经常需要对成员签名强加限制,比如c#中的构造函数.操作符重载和属性,开发者对 ...
- c#进阶之lambda表达式
阅读之前,先确保对委托有基本的了解,传送门 c#进阶之浅析委托和事件. lambda表达式雏形第一步 在委托那篇文章,绑定的的方法都是具名函数,为了简化书写,可以换成匿名函数 public deleg ...
- [uwp]自定义Behavior之随意拖动
由于最近有需求,所以自定义了一个随意拖动元素的Behavior. 当然在使用这个自定义的Behavior时,有个小假设:拖动元素必须是Canvas容器的子元素. 实现原理比较简单低效: 监听被拖动元素 ...