Binder [Android]

Binder简述

Binder(这个东东)是Android中的一种跨进程通信(IPC)的一种方式。
它的实现方式是创建了一种虚拟的物理设备,它的设备驱动是/dev/binder/。

工作机制

在Android系统的Binder机制中,有4种软件角色,是有Client,Service,ServiceManager,Binder驱动程序组成的。其中Client,service,Service Manager运行在用户空间,Binder驱动程序是运行在内核空间的。

而Binder就是把这4种组件粘合在一块的粘合剂,其中核心的组件就是Binder驱动程序,Service Manager提供辅助管理的功能,而Client和Service正是在Binder驱动程序和Service Manager提供的基础设施上实现C/S 之间的通信。
其中Binder驱动程序提供设备文件/dev/binder与用户控件进行交互,Client、Service,Service Manager通过open和ioctl文件操作相应的方法与Binder驱动程序进行通信。
而Client和Service之间的进程间通信是通过Binder驱动程序间接实现的。
而Binder Manager是一个守护进程,用来管理Service,并向Client提供查询Service接口的能力。

从Framework角度来说,Binder是ServiceManager的桥梁。
从应用层来说,Binder是客户端和服务端进行通信的媒介。

由此,它引发了Android上的一种架构,C/S,服务端与客户端的远程(进程间)通信架构
Binder是一种架构,这种架构提供了服务端接口、Binder驱动、客户端接口三个模块

简单讲,一次调用的执行流程是,经由ServiceManager查找到服务端Binder服务对象,返回其包装对象用于远程调用,客户端使用远程对象,发起远程调用,经由各种对象和机制流程(服务端远程对象,消息通信,Parcel对象参数解析,Binder机制,IPCThreadState对象),最后所有参数,由客户端的IPCThreadState.talkWithBinder(阻塞),调用Binder驱动,Binder驱动找到目标服务进程,服务端对象,给它相应的Binder线程发送消息,最后,服务端的Binder线程收到消息后进行处理,而后返回时消息时,原理是一样的。(下面有张图简单示意了这个过程,只是进程,线程关系,各种中间对象没有展示出来而已。)

中间的执行细节是:

一个Binder服务端实际上就是一个Binder类的对象,该对象一旦创建,内部就
启动一个隐藏线程。该线程接下来会接收Binder驱动发送的消息,收到消息后,会执行到Binder对象
中的onTransact()函数,并按照该函数的参数执行不同的服务代码

最后来看应用程序客户端。
客户端要想访问远程服务,必须获取远程服务在Binder对象中对应的
mRemote引用,至于如何获取,下面几节将要介绍。获得该mRemote对象后,就可以调用其transact()
方法,而在Binder驱动中,mRemote对象也重载了 transact()方法,重载的内容主要包括以下几项。
• 以线程间消息通信的模式,向服务端发送客户端传递过来的参数。
• 挂起当前线程,当前线程正是客户端线程,并等待服务端线程执行完指定服务函数后通知
(notify)
• 接收到服务端线程的通知,然后继续执行客户端线程,并返回到客户端代码区。

从这里可以看出,对应用程序开发员来讲,客户端似乎是直接调用远程服务对应的Binder,而事实
上则是通过Binder驱动进行了中转。

它的使用场景,如何使用

Framework的各种服务,应用中自建的远程Service(bind启动那种)
它在工程代码实现上,自建Binder服务,远程Service的
一种是Framework层,系统源码部分,定义接口,而后使用AIDL工具,生成服务端代码,进行相关业务接口的实现即可(如transact() onTransact()内部的实现,参数的定义等),剩下的也就是编译,集成进ROM的问题。
一种是应用层,实现远程Service。就更简单了。也是AIDL工具,生成服务端代码,定义远程Service类,继承相关接口即可。

(工程实例,步骤,代码,第一种见张的博客,第二种,网上大把)

使用注意

1、当客户端发起请求时,由于当前线程会被挂起,直到服务端返回数据,如果这个远程方法很耗时的话,那么是不能够在UI线程,也就是主线程中发起这个远程请求的。
2、由于Service的Binder方法运行在线程池中,所以Binder方法不管是耗时还是不耗时都应该采用同步的方式,因为它已经运行在一个线程中了。

3、数据大小的限制,2MB?

拓展

原理方面,实现机制上,为什么一定要驱动来实现?因为跨进程呀!
那为什么不采用传统的跨进程通信的方式? socket? 管道?内存块? 因为这是进程多对多的场景,要分离,独立,Binder起到枢纽,总管的作用。Central设计模式?

关于第一个问题,请思考为什么要用Binder。答案很简单,即为了提供一个全局服务,所谓的“全
局”,是指系统中的任何应用程序都可以访问。很明显,这是一个操作系统应该提供的最基本的功能之
一, Android的工程师自然也是这么认为的,因此,他们提供了一个更傻瓜的解决方法,那就是Service。
它 是 Android应用程序四个基本程序片段( Component)之一,四个基本片段包括Activity、Service、
Content Provier、Receiver

这种设计的作用是屏蔽直接访问远程服务,从而可以给应用程序提供灵活的、可控的A P I接口,
比如AmS。系统不希望用户直接去访问AmS,而是经过ActivityManager类去访问,而 ActivityManager
内部提供了一些更具可操作性的数据结构,比如RecentTasklnfo数据类封装了最近访问过的Task列表,
Memorylnfo数据类封装了和内存相关的信息。

猜你喜欢

转载自blog.csdn.net/Hendy_Raw/article/details/88659120