说说Binder通信

是否理解binder可以说是android学习的一个分水岭,因为这个概念太重要了,对于我们理解一系列android先关其它知识都是特别重要的,比如我们要分析Activity以及Service组件启动、ActivityManagerService以及WindowManagerService等系统服务,Binder通信都是绕不过去的一个重要知识点。这篇博客就来简单的说说Binder的通信原理吧

1、Binder通信的组成部分

Binder方式通信有4大组成部分

部分 作用
Binder Client 发起Binder通信的一方
Binder Server 接收Binder Client的消息并据此给出回应
ServiceManager 记录Binder Server的Binder句柄,Client通过ServiceManager查询目标Server的Binder句柄,并根据此Binder句柄同Server通信,同时ServiceManager本身也是一个Binder句柄为0的特殊的Server
Binder Driver Binder驱动运行于内核态,实际上通过open("/dev/binder")来打开,其是Client和Server能通信的桥梁,Client发起的求情在Driver的binder_ioctl方法中显示进行write操作写数据,然后在read操作中进入休眠,等待Server写入数据并激活Client读数据,而Server则是先进行读操作没有数据就休眠等待Client写数据激活Server处理数据

总的来说这4个部分的关系有点类似于IP通信中的Client Server Route以及DNS这4者之间的关系
在这里插入图片描述
其类比关系为

Binder IP
Binder Client Client
Binder Server Server
ServiceManager DNS
Binder Driver Route

2、Binder Client向Binder Server发起通信的具体流程

Binder Client向Binder Server发起通信的具体流程可以通过下图来说明
在这里插入图片描述
上图实际上是Binder Client向ServiceManger发起通信的流程图,前面说了ServiceManager实际上也是Binder Server,实际上我们通过这种特殊的通信流程能更容易的搞懂Binder通信原理。
感兴趣的可以去跟以下代码进行分析:

ServiceManager.getService("activity")

从上面流程图可以看到一些关键点

BpBinder @BpBinder.cpp是native层封装的IBinder对象,而BinderProxy @Binder.java则是java封装的IBinder对象,两者间通过JNI方式互相通信。实际上getService(“activity”)最终的目的也是为了获取一个带AMS服务的Binder句柄来发起与AMS服务的Binder通信。

ProcessState @ProcessState.cpp对象在初始化是就负责初开打Binder Driver(open(/dev/binder))并且建立同Binder Driver之间的联系( ioctl )

IPCThreadState @IPCThreadState.cpp通过BpBinder->transact方法调用到它的IPCThreadState -> transact方法开始真正的与Binder Driver通信

另外,从流程图也可以看出虽然BinderProxy、BpBinder、ProcessState以及IPCThreadState有些运行在java层,有些运行在native层,但是他们是运行在一个进程中的,共享进程资源。

通过以下时序图能更清晰的看到他们之前调用关系:在这里插入图片描述这个时序图可以看出显示获取handle为0的BpBinder,实际上就是对应ServiceManager的BpBinder,然后通过这个BpBinder与ServiceManger进行Binder通信,最后获取的是对应AMS句柄的BpBinder,从而与WMS进行Binder通信(这个步骤时序图没有体现)。

3、说说Client访问AMS的过程

AMS的启动时再systemserver进程中启动的,它并不是独享进程,其它服务比如WindowManagerService以及PowerManagerService都是在systemserver进程中启动,和AMS是在通一进程中的,它们都是在Android系统开机的时候被首先启动的。ServiceManager则不太一样,它是在独享server_manager进程。

AMS在systemserver中被启动,同事被添加注册到ServiceManager维护的服务列表中,并且开始循环监听是否有客户端向自己发送数据,如果当前没有数据就进入休眠状态,这一点原理上和ServiceManager是一样的,虽然在具体的实现上有差异。

Binder Client向AMS发送bindeService命令,实际上最终也是通过BpBinder向Binder Driver写数据并激活在休眠AMS线程,使得AMS开始处理数据,此时BinderClient进入休眠状态等待AMS处理完数据后写数据到Binder Driver然后激活处理休眠等待的Binder Client激活开始处理从AMS测传过来的Parcel数据。从这个流程来看无论是Binder Client端还是Binder Server端,Binder通信都是阻塞的,所以对于Binder Client来说Binder通信不能放在主线程中进行避免发生ANR,实际上对应Android应用来说,启动的时候就会自己为当前进程创建两个binder进程专门用来进行Binder通信。

这篇博客就此就算完结了,实际上对于新手来说看这篇博客意义不大,很多概念根本不知道是什么,还是建议大家看看林学森写的<深入理解Android内核设计思想> 第二版这本书吧,里面关于Binder通信说的很详细,相信能帮到大家更好的理解Binder通信的本质。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章