美文网首页
Binder原理

Binder原理

作者: jxiang112 | 来源:发表于2022-04-02 10:26 被阅读0次

相信很多Android开发的朋友大都会在面试时都会被问到Binder的原理是什么?

什么是Binder

首先先了解下Binder是什么:Binder是Android特有的一种进程间通信(简称IPC)机制,Android源自Linux,Linux的进程间通信一般有:管道、消息队里、信号量、socket、内存共享等,为什么Android要用独有Binder机制呢?我们做下对比:

通信方式 优缺点
Binder a、性能能好:只需要一次数据拷贝;
b、安全性高:使UID/PID由Binder机制本身在内核空间添加身份识别;且可以建立私有通道,这是Linux通信机制无法实现的;
c、稳定性更好:Binder基于C/S架构,客户端(Client)有什么需求都通过服务端(Server)完成,架构清晰、职责明确又相互独立,所以稳定性更好;
d、使用简单:客户端(client)函数的名字、参数和返回值与服务端(Server)的方法一样,方便使用
内存共享 优点:不需要数据拷贝,即0此数据报备;
缺点:同步、控制复杂,难以使用
管道和消息队列 缺点:性能差,因为需要2次数据拷贝(数据线从发送方缓存区拷贝到内核缓存区,再从内核缓存区拷贝到接收方的缓存区)
Socket 缺点:性能差,因为需要2次数据拷贝(传输效率低且开销比较大,一般用在跨网络的进程间通信或本机上进程间的低通信

Binder机制与角色

Binder是一种Android特有的进程间通信机制,它采用C/S通信模式,有Client、Server、ServiceManager、Binder驱动四个角色,其中Client、Server、ServiceManager都是独立进程且运行在用户空间,Binder驱动运行在内核空间:

  • Client:是客户端,服务的使用者
  • Server:是否服务提供者,需要向ServiceManager进行注册
  • ServiceManager: 是服务管理,负责服务的注册,同时管理一张服务名称与服务提供的Binder的引用的映射表,这样Client向ServicerManager请求获取服务时,通过映射表可以获取到服务提供的Binder引用,进而可以通过Binder引用进行远程调用服务提供的接口。
  • Binder驱动:是一种特殊的虚拟的字符设备,是进程间通信的桥梁。

既然Client、Server、ServiceManager都是独立的用户进程,他们之间又是进程之间通信,它们又是怎么进行通信的呢?Server是怎么注册到ServiceManager的呢?Client又是怎么获取ServiceManager的呢?答案还是Binder:

  • ServiceManger在系统启动时创建,并创建一个特殊的Binder,将它通过BINDER_SET_CONTEXT_MGR命令设置为ServiceManager的Binder驱动,它的索引为0。这个特殊的Binder没有名字也不需要注册,所有的Client和Server不需要通过其他手段,都通过索引为0的Binder与ServiceManager进行通信,如Server通过索引为0的Binder向ServiceManager注册服务,Client通过索引为0的Binder获取所需要的服务。
  • Server内部会创建一个Binder,并为其起名称,接着将其以数据包的形式,通过索引0的binder向ServiceManager发送,ServiceManager接收到之后,将名字与Binder引用进行映射。
  • Client请求服务时,通过索引0的Binder请求获取所需要的服务,ServiceManager接收到之后,根据请求的服务名称,从映射表中查询出服务提供的Binder引用,并返回给Client,接着Client就可以通过这个Binder跟Server进行通信了。

Binder进程间通信实现流程

上面介绍的只是通信的大概流程,那么具体是怎么实现的呢?比如数据流的走向怎么从Client到Server的?
在介绍实现流程之前,先大概介绍下Binder驱动提供的主要操作有:

  • open 打开驱动
  • ioctl 驱动与应用程序通信协议的实现,即Client数据到Binder驱动再到Server的通信协议由ioctl操作完成
  • mmap 内存映射

进行进程间通信,Server端需要提供一套接口函数,供Client端远程调用。一般采用代理Proxy的方式,将Server端接口函数定义在一个抽象类中,Server和Client都实现此抽象类,不同的是Server是接口函数的具体实现,Client端则是对这些远程接口的调用进行代理封装。Server端通过int类型的code来映射接口函数,在onTransact中通过判断code来调用哪个函数。
Binder进程间通信使用一套通信协议,每个协议都是命令+数据的形式,每种命令传递的数据及格式是不一样的。最常用的指令就是BINDER_WRITE_READ写读指令,而BINDER_WRITE_READ指令也是指令+数据的形式,BINDER_WRITE_READ常用的指令是BC_TRANSACT(请求)和BC_REPLY(响应)。如:Client通过索引为0的Binder获取到封装了所需要的服务Binder的代理A之后,就可以通过代理A调用服务提供的接口函数,代理内部再调用内部远程代理的Binder的transact方法向服务端发起请求,接着调用Binder驱动提供的系统接口,将请求封装为BC_TRANSACT数据包和BINDER_WRITE_READ数据包,Binder驱动使用mmap将Server端和内核空间都映射到同一块地址,接着调用copy_from_user将请求的数据拷贝的内核空间与Server映射好的内存中,binder驱动通过ioctl操作对数据进行解析,再调用服务端的读onTransact操作进行处理,服务端的onTransact的响应也是一样类似的操作逆序将响应信息传回给Client。

相关文章

网友评论

      本文标题:Binder原理

      本文链接:https://www.haomeiwen.com/subject/aaurhrtx.html