【新手入门】Android基础知识(二):Binder进程间通信,理解Binder工作原理以及Binder实体、Binder引用、Binder代理概念
目 录
C/S通信机制
编辑
Binder通信模型
Binder工作原理
BInder实体、Binder代理、Binder引用
服务调用
服务注册
服务获取
参考资料
Binder是Android平台的一种跨进程通信( IPC, Inter Process Communication)机制,允许应用间能够以程序调用的方式进行通信,而无须关心消息到底是如何发送和接收的。
C/S通信机制
C/S通信指的就是Client和Server两个进程的通信,但实际通信时除了包含这两个进程,还有一个Service Manager,它用于管理各种服务。
-
当Server(服务端)想要提供服务,首先需要在Service Manager注册该服务;
-
当Client(客户端)想要使用Server中的服务时,不能直接访问,而是要从Service Manager获取该服务,才能使用Server所提供的服务,来与Server进行通信。
Binder通信模型
在引入Binder机制后,客户端、服务端和Service Manager之间不能通过api直接互相访问,而是与内核空间的Binder驱动通过ioctl方式来完成进程间的数据交换。
Binder工作原理
BInder实体、Binder代理、Binder引用
-
Binder 实体:也称为Binder node(Binder 节点),由内核中的 Binder 驱动创建,是运行在服务端Server进程中的 Binder 对象。由服务端进程在启动时创建,并注册到 Binder 驱动。
-
Binder 代理:在用户空间创建,是客户端进程中的Binder对象,代表服务端的 Binder 实体。当客户端需要访问服务时,通过 Binder 驱动获取服务的 Binder 代理。
-
Binder 引用:由内核中的 Binder 驱动创建,用于引用 Binder 实体,位于内核空间。当客户端首次访问某个服务时,Binder 驱动会创建一个 Binder 引用对象,并将其与对应的 Binder 实体关联。用于维护 Binder 实体的生命周期,确保服务端对象可以被客户端正确访问。
服务调用
每个节点都可以公开和实现自己的接口。借助代理,客户端可以像调用本地函数一样在节点接口上执行方法。下图展示了此调用的执行方式:
客户端发起请求 → Binder 代理转发请求 → 内核传递请求 → Binder 节点转发请求 → 服务端处理请求 → 返回结果 → 客户端接收结果
假设调用foo()的客户端在进程 A 中运行,而实现foo()的服务器在进程 B 中运行。如上图所示,如需在另一个进程中执行方法,会发生以下情况:
-
进程 A 中的客户端代码调用进程 A 中的代理代码。进程 A 中的代理代码创建了一个包含以下项的交易:节点的标识符、节点上foo() 方法的标识符、包含实参a和b副本的缓冲区
-
事务已提交给 Binder 内核驱动程序。
-
Binder 内核驱动程序确定进程 B 托管该节点。
-
内核将整个事务复制到进程 B 的地址空间中。
-
内核在进程 B 中找到一个线程来处理事务,并将事务传递给该线程。
-
线程解封装事务,找到节点,并将事务发送到节点对象。
-
节点对象从交易中获取函数标识符,从交易缓冲区中解封
a
和b
,并将a
和b
存储在局部变量中。 -
节点对象在进程 B 中对服务器代码调用
foo(a, b)
。 -
调用的结果在回复事务中返回,该事务会传递给内核驱动程序,然后返回到进程 A 中的调用代理。
-
代理将该结果返回给进程 A 中的调用方。
服务注册
当一个新的服务(Service)启动时,它会向 Service Manager 注册自己。通常在服务的 onCreate 方法中完成。
在注册服务的过程中,server进程是客户端,而service manager是服务端。
- server进程向binder驱动申请创建服务的binder实体
- binder驱动为这个服务创建位于内核的binder实体和binder引用
- 创建完成后,服务端通过binder驱动将binder引用发送给service manager
- service manager收到数据后,取出被创建服务的名字和引用,填入一张查找表
服务获取
当客户端需要与某个服务通信时,它会向 Service Manager 查询该服务的 Binder 引用,通过调用 Context.bindService 方法来查找服务。
1. Client进程利用handle值为0的引用找到service manager
在 Android 中,每个进程在启动时都会自动获取 Service Manager 的 Binder 引用,这个引用的 handle 值固定为 0。
客户端进程通过这个 handle 值(0)来查找和访问 Service Manager。
2. Client进程向service manager发送xxxservice的访问申请
3. service manager从请求表中获取xxxservice的名字,在查找表中找到对应的条目,取出对应的binder引用
4. service manager把xxxservice的binder引用传给Client进程
参考资料
-
架构概览 | Android Open Source Project
-
Android中的Binder_android binder-CSDN博客
-
Android IPC --Binder之架构篇(二)_binder大概分了几层-CSDN博客
-
《疯狂Android讲义》