02 Binder基础 -大管家 ServiceManager
02 Binder基础 -大管家 ServiceManager
Binder 基础 - ServiceManager
ServiceManager
SeriveManager 介绍
疑问: 使用 Binder 框架的既包括系统服务,也包括第三方应用。因此,在同一时刻,系统中会有大量的 Server 同时存在。那么,Client 在请求 Server 的时候,是如果确定请求发送给哪一个 Server 的呢?
解决的方法就是:每个目标对象都需要一个唯一的标识。并且,需要有一个组织来管理这个唯一的标识。
而 Binder 框架中负责管理这个标识的就是ServiceManager。ServiceManager 对于 Binder Server的管理
就好比车管所对于车牌号码的的管理,派出所对于身份证号码的管理:每个公开对外提供服务的 Server 都需要注册到 ServiceManager 中(通过 addService),注册的时候需要指定一个唯一的 id(这个 id 其实就是一个字符串)。
Client 要对 Server 发出请求,就必须知道服务端的 id。Client 需要先根据 Server 的 id 通过 ServerManager 拿到 Server 的标示(通过 getService),然后通过这个标示与 Server 进行通信。
整个过程如下图所示:
servicemanager 启动流程
当 Kernel 启动加载完驱动之后,会启动 Android 的 init 程序,init 进程加载了 servicemanager 的 rc 可执行程序之后加载了 servicemanager 的入口函数启动了 servicemanager 进程。
servicemanager 启动分为三步:
- 首先打开 Binder 驱动创建全局链表
binder_procs
- 将自己当前进程信息保存到
binder_procs
链表 - 开启
binder_loop
不断地处理共享内存中的数据,并处理BR_xxx
命令
servicemanager 作用?
- binder 机制的守护进程,Binder 上下文管理者(其他调用者通过预留的 0 号引用获取 servicemanager 的 binder);
- 注册服务(针对 Server)
- 查询服务(针对 Client)
ServiceManager 注册服务
- 通过 ServiceManager 的 addService() 方法来注册服务
- ServiceManager 向 Binder 驱动发送
BC_TRANSACTION
命令 (ioctl 的命令,BC 可以理解为 Binder Client 发过来的请求命令) 携带ADD_SERVICE_TRANSACTION
命令,同时注册服务的线程进入等待状态waitForResponse()
- Binder 驱动收到请求命令向 ServiceManager 的 todo 队列里面添加一条注册服务的事务,事务的任务就是创建服务端进程 binder_node 信息并插入到 binder_procs 链表中
- 事务处理完之后发送
BT_TRANSACTION
命令,ServiceManager 收到命令后向svcinfo
列表中添加已经注册的服务,最后发送BR_REPLY
命令唤醒等待的线程,通知注册成功
ServiceManager 获取服务
- 通过 ServiceManager 的 getService() 方法来注册服务
- ServiceManager 向 binder 驱动发送
BC_TRANSACTION
命令携带CHECK_SERVICE_TRANSACTION
命令,同时获取服务的线程进入等待状态waitForResponse()
- Binder 驱动收到请求命令向 ServiceManager 发送
BC_TRANSACTION
查询已注册的服务,查询到直接响应BR_REPLY
唤醒等待的线程;若查询不到将与 binder_procs 链表中的服务进行一次通讯再响应
servicemanager 一些疑问?
Client 和 Server 怎么获取 servicemanager 的 binder 对象?
通过 getStrongProxyForHandle(0)
方法获取,因为 servicemanager 默认就是 0 号引用,便于其它系统服务查询使用,它内部会根据句柄创建对应的 BpBinder 对象
本文由作者按照 CC BY 4.0 进行授权