在Binder纯理论分析中介绍了Binder
的整个通信流程。
下面我们直接通过Service
的注册来了解一下Binder
的具体工作原理。
我们以MediaService
为例,来看下service
的注册过程。MediaService
对应的启动文件在main_mediaserver.cpp
中的main
方法。
代码语言:javascript复制frameworks/av/media/mediaserver/main_mediaserver.cpp
int main(int argc __unused, char **argv __unused)
{
signal(SIGPIPE, SIG_IGN);
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm(defaultServiceManager());
ALOGI("ServiceManager: %p", sm.get());
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
registerExtensions();
::android::hardware::configureRpcThreadpool(16, false);
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
::android::hardware::joinRpcThreadpool();
}
ProcessState
首先创建了ProcessState
,它使用了sp
的强引用类型。
ProcessState::self
内部是一个单例,如果为空它会创建ProcessState
对象
ProcessState::ProcessState(const char *driver)
: mDriverName(String8(driver))
, mDriverFD(open_driver(driver)) // 启动binder驱动
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mWaitingForThreads(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS) // 设置最大线程数
, mStarvationStartTimeMs(0)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
, mCallRestriction(CallRestriction::NONE)
{
if (mDriverFD >= 0) {
// 映射虚拟内存地址
mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
// *sigh*
ALOGE("Using %s failed: unable to mmap transaction memory.n", mDriverName.c_str());
close(mDriverFD);
mDriverFD = -1;
mDriverName.clear();
}
}
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver '%s' could not be opened. Terminating.", driver);
}
上面是ProcessState
的实例化过程,主要有以下三个重要的设置。
- open_driver(driver): 启动
binder
驱动 - mMaxThreads(DEFAULT_MAX_BINDER_THREADS): 设置最大线程数16
- mmap: 映射虚拟内存地址
static int open_driver(const char *driver)
{
// 打开binder驱动
int fd = open(driver, O_RDWR | O_CLOEXEC);
if (fd >= 0) {
int vers = 0;
// 通过ioctl与binder驱动交互,获取binder版本信息
status_t result = ioctl(fd, BINDER_VERSION, &vers);
if (result == -1) {
ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd = -1;
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
ALOGE("Binder driver protocol(%d) does not match user space protocol(%d)! ioctl() return value: %d",
vers, BINDER_CURRENT_PROTOCOL_VERSION, result);
close(fd);
fd = -1;
}
// 设置最大线程数
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
} else {
ALOGW("Opening '%s' failed: %sn", driver, strerror(errno));
}
return fd;
}
在open_driver
中通过open
打开binder
驱动,在binder
驱动中对应的方法是binder_open
,它会创建binder_proc
对象,并将进程等相关信息保存到binder_proc
对象中,并返回fd
文件描述符。
在Linux
中通过ioctl
方法与设备进行交互,获取binder
的版本信息,同时设置binder
的最大线程数16。在binder
驱动中对应的是binder_ioctl
方法,该方法主要通过fd
文件描述符、ioctl
命令与数据类型来传递数据。
在ProcessState
创建的过程中,会通过mmap
方法,在binder
驱动中对应的是binder_mmap
方法,将内核中同一块物理内存分别映射到内核的虚拟内存地址空间与用户的虚拟内存地址空间,保证内核空间buffer
与用户空间buffer
的同步操作。
以上就是ProcessState
的主要流程。
下面继续main
方法中的下一步操作。
BpServiceManager
代码语言:javascript复制sp<IServiceManager> sm(defaultServiceManager());
获取IServiceManager
对象,所以我们进入defaultServiceManager
方法
sp<IServiceManager> defaultServiceManager()
{
std::call_once(gSmOnce, []() {
sp<AidlServiceManager> sm = nullptr;
while (sm == nullptr) {
// 重要方法,获取ServiceManager
sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr));
if (sm == nullptr) {
ALOGE("Waiting 1s on context object on %s.", ProcessState::self()->getDriverName().c_str());
sleep(1);
}
}
gDefaultServiceManager = new ServiceManagerShim(sm);
});
return gDefaultServiceManager;
}
在该方法中我们发现它会通过interface_cast
来获取sm
,这里的AidlServiceManager
本质就是IServiceManager
。我们先把这个方法放一放,先看下它的参数获取
ProcessState::self()->getContextObject(nullptr)
嗯,又看到了ProcessState::self()
,前面已经分析了,它就是一个ProcessState
单例,所以直接看getContextObject
方法
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
sp<IBinder> context = getStrongProxyForHandle(0);
if (context == nullptr) {
ALOGW("Not able to get context object on %s.", mDriverName.c_str());
}
internal::Stability::tryMarkCompilationUnit(context.get());
return context;
}
返回了IBinder
,这是我们第一次看到IBinder
,感觉有点眉目了,继续看getStrongProxyForHandle(0)
,注意它这里传了一个参数0
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
if (e != nullptr) {
IBinder* b = e->binder;
if (b == nullptr || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
Parcel data;
// 数据传输
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, nullptr, 0);
if (status == DEAD_OBJECT)
return nullptr;
}
// 创建BpBinder
b = BpBinder::create(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
IPCThreadState::self()
也是一个单例,通过它的transact
方法向远端发送数据,关于数据的发送本期不分析,所以我们暂且跳过。
继续,创建了BpBinder
,并将handler = 0
传给它,最终通过result
返回的就是BpBinder(0)
,此时已经获取到了IBinder
,作为跨进程通信的载体。
所以我们向上回退,回到最初的地方interface_cast
,现在已经知道它的参数其实就是BpBinder(0)
,即interface_cast(BpBinder(0))
。
现在就只剩下interface_cast
了,只要我们解开它就能知道ServiceManager
是如何创建并获取的。
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
发现它调用了INTERFACE
的asInterface
方法,那么INTERFACE
又是什么呢?
找了一圈发现它居然是一个模板,声明如下
代码语言:javascript复制 #define DECLARE_META_INTERFACE(INTERFACE)
public:
static const ::android::String16 descriptor;
static ::android::sp<I##INTERFACE> asInterface(
const ::android::sp<::android::IBinder>& obj);
virtual const ::android::String16& getInterfaceDescriptor() const;
I##INTERFACE();
virtual ~I##INTERFACE();
static bool setDefaultImpl(std::unique_ptr<I##INTERFACE> impl);
static const std::unique_ptr<I##INTERFACE>& getDefaultImpl();
private:
static std::unique_ptr<I##INTERFACE> default_impl
这里的INTERFACE
就是ServiceManager
,在模板声明中看到了我们所要的asInterface
。
下面再看模板函数的具体实现
代码语言:javascript复制IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)
const ::android::StaticString16
I##INTERFACE##_descriptor_static_str16(__IINTF_CONCAT(u, NAME));
const ::android::String16 I##INTERFACE::descriptor(
I##INTERFACE##_descriptor_static_str16);
const ::android::String16&
I##INTERFACE::getInterfaceDescriptor() const {
return I##INTERFACE::descriptor;
}
::android::sp<I##INTERFACE> I##INTERFACE::asInterface(
const ::android::sp<::android::IBinder>& obj)
{
::android::sp<I##INTERFACE> intr;
if (obj != nullptr) {
intr = static_cast<I##INTERFACE*>(
obj->queryLocalInterface(
I##INTERFACE::descriptor).get());
if (intr == nullptr) {
intr = new Bp##INTERFACE(obj);
}
}
return intr;
}
...
将INTERFACE
替换成ServiceManager
来看,最终通过asInterface
返回的是BpServiceManager
对象,同时它的参数obj
对应的就是之前的BpBinder(0)
。
搞明白这个之后,再回到最初的地方(希望没有晕),对应的就是defaultServiceManager
方法。
所以每次调用defaultServiceManager
其实就是返回BpServiceManager(BpBinder(0))
对象。
最后我们再来看下BpServiceManager
,它在IServiceManager.cpp
就申明的
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
explicit BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
{
}
virtual sp<IBinder> getService(const String16& name) const
{ ... }
virtual sp<IBinder> checkService( const String16& name) const
{ ... }
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated, int dumpsysPriority) { ... }
...
};
它提供了addService
与getService
方法,暂时不分析,但可以大胆猜一下,应该是通过BpServiceManager
的这些方法来注册与获取对应的Service
。至于它内部又是如何传递到ServiceManager
我们后续再分析。
回到最初的main
方法,我们接下来应该就是
MediaPlayerService::instantiate();
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
}
再来看instantiate
就简单许多了,它通过defaultServiceManager
向其中注册了名称为media.player
的MediaPlayerService
服务。
而defaultServiceManager
对应的是BpServiceManager(BpBinder(0))
,所以上面我们的猜想是成立的。关于服务的注册、验证与获取都是通过BpServiceManager
代理完成的,其实内部最终都是通过BpBinder(0)
来传输的。
好了,为了尽量缩短篇幅,降低阅读疲劳,提升读者体验,这篇文章就分析到这里。
下面来总结一下MediaService
所做的一部分核心内容
- 创建
ProcessState
对象 - 在
ProcessState
的创建过程中启动binder
驱动,使用ioctl
与binder
驱动交互,并设置binder
最大并发线程数16,使用mmap
映射虚拟内存地址 - 创建
IPCThreadState
对象,使用transact
向server
端发送数据 - 创建
BpBinder
对象,获取IBinder
,作为跨进程通信的载体 - 创建
BpServiceManager
对象,作为服务注册、检验与获取的代理