binder 情景分析 - service 的注册(上)
本篇为 service 注册的第一篇,主要讲述一些原理性的东西。service 注册部分只讲到获取 IServiceManager 对象。
RPC 原理简述
在开始之前,我们先来了解一下基本的原理。

不同进程之间进行通信时,本质上还是只能够交换一下数据。方法、函数的调用是能够跨进程的。为了实现跨进程的函数调用,我们在原有 client 和 service 的基础上,增加两个对象——proxy 和 stub。客户端调用的,其实是 proxy 的函数。proxy 通过某些 IPC 通道,告知 stub。stub 读取 proxy 发生的数据,得知需要调用的函数后,再回调 service 对应的函数。
这样,从 client 和 service 的角度看,就好像是 client 调了 service 的函数。
基本的服务注册流程
从应用的角度,服务的注册其实非常简单:
1 | sp<IServiceManager> manager = defaultServiceManager(); |
这样,就成功注册了一个叫 serv_name 的服务。下面,我们就详细了解一下,在两个简单的调用背后,到底发生了什么。
注:以下 framework 源码使用 oreo-release 分支,kernel 部分使用 common 的 android-4.9-o-release 分支。部分代码为了可读性,在不影响结果的情况下作了删改。
获取 context manager 的 IBinder
我们先来看看 defaultServiceManager() 函数:
1 | // frameworks/native/libs/binder/IServiceManager.cpp |
这里关键的一句,便是:
1 | gDefaultServiceManager = interface_cast<IServiceManager>( |
getContextObject(NULL) 返回的,便是指向 context manager 的 sp<IBinder>:
1 | // frameworks/native/libs/binder/ProcessState.cpp |
这里的 handle 类似于文件描述符,通过这个 handle,binder 驱动就可以找到对应的 struct binder_node,而 binder_node 则关联着对应的服务。而 handle = 0 特指 context manager。
lookupHandleLocked() 会先查找本地的缓存。如果已经为对应的 handle 生成过 BpBinder,则直接返回。即便没有,lookupHandleLocked() 也会创建一个 handle_entry,但是 e->binder 为空。接下来 new BpBinder(handle),并把新生成的对象放到缓存中。
各个类之间的关系
BpBinder 实际上是 IBinder 的类。在本篇中会涉及到的类之间的继承关系如下:

前面我们获取的 BpBinder 其实是 IBinder 的子类。以 BpXXX 方式命名的,都是运行在客户端的代理。
IBinder 和 IInterface 之间的转换关系下:

IInterface 在下面一节开始说明。
获取 IServiceManager 代理对象
1 | gDefaultServiceManager = interface_cast<IServiceManager>( |
再次回到一开始的这里,现在我们知道,ProcessState::self()->getContextObject(NULL) 会返回一个指向 BpBinder 的 sp<IBinder>。
下面是 interface_cast:
1 | // frameworks/native/libs/binder/include/binder/IInterface.h |
展开模板后是这样:
1 | inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj) |
而 IServiceManager::asInterface() 是用宏生成的:
1 | // frameworks/native/libs/binder/IServiceManager.cpp |
展开后,IServiceManager::asInterface() 是这样的:
1 | sp<IServiceManager> IServiceManager::asInterface(const sp<::android::IBinder>& obj) |
从上面的类关系,我们知道,BpBinder 继承了 IBinder。同时,它也继承了 queryLocalInterface 的实现:
1 | // frameworks/native/libs/binder/Binder.cpp |
上面的代码最终会执行 intr = new BpServiceManager(obj);,返回的是一个 BpServiceManager 对象。
到这里,我们就完成了服务注册的第一步——获取一个 IServiceManager,还知道了它实际上是一个 BpServiceManager。
1 | // frameworks/native/libs/binder/IServiceManager.cpp |
在 BpServiceManager 的构造函数里,它只是简单地将 BpBinder 传递给了父类 BpInterface。BpInterface 有继续传给父类,最终到了 BpRefBase,存在了成员变量 mRemote 里。
通过 remote() 函数,我们就可以重新拿到底层的 BpBinder 对象。
现在,我们终于完成了第一部分——获取一个 IServiceManager 对象。下一篇,我们再继续第二部分——服务的注册。