1.Binder通信模型
要讲解Binder的通信模型,我们首先需要了解网络的通信模型。
1.1网络请求的通信模型
通常我们访问一个网页的步骤是这样的:首先在浏览器输入一个地址,如 www.google.com 然后按下回车键。但是并没有办法通过域名地址直接找到我们要访问的服务器,因此需要首先访问 DNS 域名服务器,域名服务器中保存了 www.google.com 对应的 ip 地址 10.249.23.13,然后通过这个 ip 地址才能放到到 www.google.com 对应的服务器。
它的通信模型是这样的:
- Server端向DNS服务器注册自己的域名和IP,因此NDS服务器中存储了所有的域名和IP的对于的信息表;
- Client端先通过域名去访问网络服务,但是域名却不能给client端打通服务,因为访问服务是通过IP进行;
3)这个时候为了通过域名找到IP地址,所以首先会通过路由器先去访问DNS服务器,通过DNS服务器的域名解析拿到IP地址;
4)client端在拿到DNS给的IP地址后,通过IP地址由路由器去访问服务器,完成网络请求。

1.2 切换到binder中的说明
Binder通信的模型就和上面的网络通信模型有着异曲同工之妙。在角色方面,Client进程就等同于网络请求的Client端,服务器就是Server进程,路由器相当于Binder驱动,而DNS服务器相当于ServiceManager进程。Binder 驱动就如同路由器一样,是整个通信的核心;驱动负责进程之间 Binder 通信的建立,Binder 在进程之间的传递,Binder 引用计数管理,数据包在进程之间的传递和交互等一系列底层支持。
ServiceManager 和 DNS 类似,作用是将字符形式的 Binder 名字转化成 Client 中对该 Binder 的引用,使得 Client 能够通过 Binder 的名字获得对 Binder 实体的引用。注册了名字的 Binder 叫实名 Binder,就像网站一样除了有 IP 地址以外还有自己的网址(域名)。Server 创建了 Binder,并为它起一个可读易记得名字,比如AMS的binder,我们就取了一个名字叫做"activity",将这个 Binder 实体连同名字一起以数据包的形式通过 Binder 驱动发送给 ServiceManager ,通知 ServiceManager 注册一个名为"activity"的 Binder,它位于某个 Server 中。而ServcieManager中就存储了一个表格,这个表格中就有名字和binder引用对应的信息item。
Client 获得实名 Binder 的引用
在这个代码 ServiceManager.getService(Context.ACTIVITY_SERVICE) //String ACTIVITY_SERVICE = "activity",这段代码是Client去ServcieManager中获取server进程的binder的代码,这个地方获取的是AMS的binder实体的代码。代码的设计逻辑就是去ServcieManager的查找表容器中去获取名字为activity的binder实体。
Server 向 ServiceManager 中注册了 Binder 以后, Client 就能通过名字获得 Binder 的引用了。Client 也利用保留的 0 号引用向 ServiceManager 请求访问某个 Binder: 我申请访问名字叫张三的 Binder 引用。ServiceManager 收到这个请求后从请求数据包中取出 Binder 名称,在查找表里找到对应的条目,取出对应的 Binder 引用作为回复发送给发起请求的 Client。从面向对象的角度看,Server 中的 Binder 实体现在有两个引用:一个位于 ServiceManager 中,一个位于发起请求的 Client 中。如果接下来有更多的 Client 请求该 Binder,系统中就会有更多的引用指向该 Binder ,就像 Java 中一个对象有多个引用一样。

2.Binder通信的流程
Binder框架定义了四个角色:Server,Client,ServiceManager(以后简称SMgr)以及Binder驱动。其中Server,Client,SMgr运行于用户空间,驱动运行于内核空间。这四个角色的关系和互联网类似:Server是服务器,Client是客户终端,SMgr是域名服务器(DNS),驱动是路由器。
在网络通信中域名服务器的地址是一个固定的地址,所以很方便的通过这个固定地址拿到。那么在Binder中,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。
有了以上的知识铺垫,我们可以比较清晰的把BInder通信的流程梳理出来:
- 首先,一个进程使用 BINDERSETCONTEXT_MGR 命令通过 Binder 驱动将自己注册成为 ServiceManager;
- Server 通过驱动向 ServiceManager 中注册 Binder(Server 中的 Binder 实体),表明可以对外提供服务。驱动为这个 Binder 创建位于内核中的实体节点以及 ServiceManager 对实体的引用,将名字以及新建的引用打包传给 ServiceManager,ServiceManger 将其填入查找表。
- Client 通过名字,在 Binder 驱动的帮助下从 ServiceManager 中获取到对 Binder 实体的引用。
- 通过这个Binder实体引用,Client实现和 Server 进程的通信。
今日分享到此结束,对你有帮助的话,点个赞再走呗,如遇侵权联系删除
关注公众号:Android老皮解锁 《Android十大板块文档》 ,让学习更贴近未来实战。已形成PDF版
内容如下:
1.Android车载应用开发系统学习指南(附项目实战)
2.Android Framework学习指南,助力成为系统级开发高手
3.2023最新Android中高级面试题汇总+解析,告别零offer
4.企业级Android音视频开发学习路线+项目实战(附源码)
5.Android Jetpack从入门到精通,构建高质量UI界面
6.Flutter技术解析与实战,跨平台首要之选
7.Kotlin从入门到实战,全方面提升架构基础
8.高级Android插件化与组件化(含实战教程和源码)
9.Android 性能优化实战+360°全方面性能调优
10.Android零基础入门到精通,高手进阶之路