一 概述
Binder是Android中的一种IPC机制,在Binder中,Binder是基于C/S架构的,但是除了C/S架构中的Client和Server,Android中还有一个ServiceManager,它的作用就是管理各种服务,我们在Service的启动中已经见识过它了。
接下来,在我们深入学习Binder之前,我们先通过Android系统自己对于Binder的使用,来了解Binder,在这里,我们选择的目标是MediaServer
源码目录
frameworks/av/media/mediaserver/main_mediaserver.cpp
frameworks/native/libs/binder/ProcessState.cpp
frameworks/native/libs/binder/IServiceManager.cpp
frameworks/native/libs/binder/BpBinder.cpp
frameworks/native/libs/binder/include/binder/IInterface.h
frameworks/native/libs/binder/IServiceManager.cpp
frameworks/native/libs/binder/Binder.cpp
frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
frameworks/native/libs/binder/BpBinder.cpp
frameworks/native/libs/binder/IPCThreadState.cpp
二 MediaServer的入口
MediaServer的入口函数如下,这是一个非常标准的Binder使用流程
[main_mediaserver.cpp]
int main(int argc __unused, char **argv __unused)
{
signal(SIGPIPE, SIG_IGN);
//1 获得一个ProcessState的实例
sp<ProcessState> proc(ProcessState::self());
//2 获得一个IServiceManager对象
sp<IServiceManager> sm(defaultServiceManager());
ALOGI("ServiceManager: %p", sm.get());
AIcu_initializeIcuOrDie();
//3 注册服务
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
//4 注册其他,默认为空
registerExtensions();
//5 ProcessState有关线程池
ProcessState::self()->startThreadPool();
//6 IPCThreadState有关线程池
IPCThreadState::self()->joinThreadPool();
}
在上述代码中,我们看到了大致6个步骤,接下来,我们就对这6个步骤进行一一分析
三 ProcessState
看步骤1的代码,我们也能大致猜测出来,它是一个单例,这个self方法具体如下
[ProcessState.cpp]
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != nullptr) {
return gProcess;
}
//第一次执行一定为空,需要创建对象,所以会执行构造函数
gProcess = new ProcessState(kDefaultDriver);
return gProcess;
}
3.1 ProcessState的构造函数
[ProcessState.cpp]
ProcessState::ProcessState(const char *driver)
: mDriverName(String8(driver))
//这里是关键点
, mDriverFD(open_driver(driver))
, ...
{
if (mDriverFD >= 0) {
//调用一个mmap,拿到起始地址
mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
// 如果mmap映射失败,一般不会执行
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 could not be opened. Terminating.");
}
3.2 open_driver
[ProcessState.cpp]
static int open_driver(const char *driver)
{
//打开binder驱动
int fd = open(driver, O_RDWR | O_CLOEXEC);
if (fd >= 0) {
int vers = 0;
//通过ioctl的方式与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;
//最大线程数,默认是15
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: %s\n", driver, strerror(errno));
}
return fd;
}
到这里,Process的构造函数就算是结束了,它主要的工作如下
- 打开binder驱动(默认是/dev/binder),获得一个fd
- 对于返回的fd使用mmap,这样Binder驱动就会分配一块内存来接收数据
- Process是单例的
四 defaultServiceManager
defaultServiceManager是IServiceManager中的一个函数,它返回了一个IServiceManager对象,它也是一个单例
[IServiceManager.cpp ]
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != nullptr) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == nullptr) {
//创建一个gDefaultServiceManager对象
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(nullptr));
//如果为空,就循环等待
if (gDefaultServiceManager == nullptr)
sleep(1);
}
}
return gDefaultServiceManager;
}
在defaultServiceManager中,首先会通过getContextObject来获取一个gDefaultServiceManager对象,如果没有获取到,那么就会循环等待,这里我们有两个问题
- getContextObject是如何获取的gDefaultServiceManager
- 什么情况下会获取不到
首先我们思考第一个问题,getContextObject做了什么
4.1 getContextObject
getContextObject是ProcessState中的函数,具体如下
[ProcessState.cpp]
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}
[ProcessState.cpp]
//通过一个int的handle值,来获得一个IBinder
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
//根据handle值来查找
handle_entry* e = lookupHandleLocked(handle);
if (e != nullptr) {
//拿到查找对象中的IBinder
IBinder* b = e->binder;
if (b == nullptr || !e->refs->attemptIncWeak(this)) {
//如果IBinder为空
if (handle == 0) {
//handle值为0
Parcel data;
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, nullptr, 0);
if (status == DEAD_OBJECT)
return nullptr;
}
//根据handle值创建一个BpBinder
b = BpBinder::create(handle);
//填充entry
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
4.2 BpBinder
在getStrongProxyForHandle函数中,我们看到了一个对象叫BpBinder,关于BpBinder,这里简单说明一下
-
在Android中,使用BInder通信时,一般都会有两个对象BpBinder和BBinder
-
它们都是继承自IBinder而来的,BpBinder代表客户端,BBinder代表服务端
-
这里创建时传入的handle值0就是它们用来对应的标识
关于BpBinder的构造函数如下
[BpBinder.cpp]
BpBinder::BpBinder(int32_t handle, int32_t trackedUid)
: mHandle(handle)
, mAlive(1)
, mObitsSent(0)
, mObituaries(nullptr)
, mTrackedUid(trackedUid)
{
ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
IPCThreadState::self()->incWeakHandle(handle, this);
}
这个构造函数很简单,接下来我们再看拿到了这个BpBInder对象之后又做了什么
4.3
经过BpBInder对象的构造,我们可以将之前代码简化
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(nullptr));
//因为ProcessState::self()->getContextObject(nullptr)获得的是一个BpBInder
//所以如上代码如下
gDefaultServiceManager = interface_cast<IServiceManager>(new BpBInder(0));
然后通过interface_cast将这个对象转化成IServiceManager,关于interface_cast,它是模板函数
[IInterface.h]
//模板函数
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
//宏定义如下
#define DECLARE_META_INTERFACE(INTERFACE) \
public: \
static const ::android::String16 descriptor; \
static ::android::sp<I##INTERFACE> asInterface( \
const ::android::sp<::android::IBinder>& obj); \
...
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
...
::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; \
}
然后通过两个宏定义DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE,就将它们关联起来了
[IServiceManager.h]
class IServiceManager : public IInterface
{
public:
DECLARE_META_INTERFACE(ServiceManager)
...
}
并且在IServiceManager.cpp
中,有一行IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager")
所以上述的interface_cast(new BpBInder(0));
最后其实是创建了一个BpServiceManager
4.3 BpServiceManager
接下来,我们看看这个创建过程发生了哪些事情,首先我们先看BpServiceManager的继承关系
首先是BpServiceManager的构造函数,它是IServiceManager.cpp的一个内部类
[IServiceManager.cpp]
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
explicit BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
...
然后是BpInterface,它是IInterface.h的一个内部类
[IInterface.h]
template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
: BpRefBase(remote)
...
接下来是BpRefBase,它是Binder.cpp的一个内部类
[Binder.cpp]
BpRefBase::BpRefBase(const sp<IBinder>& o)
: mRemote(o.get()), mRefs(nullptr), mState(0)
...
通过 BpServiceManager -> BpInterface -> BpRefBase,最后将我们传入的一个BpBinder和一个mRemote关联了起来,到这里,我们的准备工作就算是完成了
五 IPCThreadState
5.1 服务的注册
在main_mediaserver.cpp的第三步MediaPlayerService::instantiate();
,就是服务的注册
[MediaPlayerService.cpp]
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
}
如果看过SystemServer的源码,就会发现里面有很多这样addService注册服务的逻辑,这里的defaultServiceManager在前面我们已经说了,它是一个BpServiceManager对象,它继承自IServiceManager,它的addService方法如下
[IServiceManager::BpServiceManager]
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated, int dumpsysPriority) {
//这里有一个Parcel,这个对象是Android中跨进程通信的重要对象,数据就保存在这里面
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
data.writeInt32(dumpsysPriority);
//这个remote()就是我们创建时候传入的BpBinder
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
这里我们看到了一个transact,这个方法我们以后会经常看见,它就是和Binder交互的重要函数
5.2 IPCThreadState的创建
刚才我们说到了Binder的具体交互函数transact,它是定义在BpBinder中的,接下来我们就看看BpBinder中的具体逻辑
[BpBinder.cpp]
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
// Once a binder has died, it will never come back to life.
if (mAlive) {
//关键点,IPCThreadState
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
这里我们看到了一个IPCThreadState,这个类也是Binder通信中非常重要的类,我们先看它的self方法
[IPCThreadState.cpp]
IPCThreadState* IPCThreadState::self()
{
//第一次是false
if (gHaveTLS) {
restart:
//在restart中创建IPCThreadState对象
const pthread_key_t k = gTLS;
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
if (st) return st;
return new IPCThreadState;
}
//第一次是false
if (gShutdown) {
ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
return nullptr;
}
//线程锁
pthread_mutex_lock(&gTLSMutex);
if (!gHaveTLS) {
int key_create_value = pthread_key_create(&gTLS, threadDestructor);
if (key_create_value != 0) {
pthread_mutex_unlock(&gTLSMutex);
ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n",
strerror(key_create_value));
return nullptr;
}
gHaveTLS = true;
}
pthread_mutex_unlock(&gTLSMutex);
//跳转到restart
goto restart;
}
可以看出这个是一个和线程相关的单例,在同一个线程下它只有一个对象,接下来我们再看它的构造函数
[IPCThreadState.cpp]
IPCThreadState::IPCThreadState()
: mProcess(ProcessState::self()),
mWorkSource(kUnsetWorkSource),
mPropagateWorkSource(false),
mStrictModePolicy(0),
mLastTransactionBinderFlags(0),
mCallRestriction(mProcess->mCallRestriction)
{
//和线程相关联
pthread_setspecific(gTLS, this);
clearCaller();
//和Binder驱动交互的两个缓冲区
mIn.setDataCapacity(256);
mOut.setDataCapacity(256);
mIPCThreadStateBase = IPCThreadStateBase::self();
}
然后在构造函数中,初始化了两个缓冲区mIn和mOut,这个mIn是从Binder设备读数据的,而mOut则是向Binder设备写数据的
5.3 transact
接下来我们就要看最关键的transact
[IPCThreadState.cpp]
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
...
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);
...
if ((flags & TF_ONE_WAY) == 0) {
...
if (reply) {
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
...
} else {
err = waitForResponse(nullptr, nullptr);
}
return err;
}
transact中的逻辑非常长,并且里面还有很多判断,不过这里不论是哪个分支,都会调用到两个方法,分别是writeTransactionData和waitForResponse,接下来我们就看看这个waitForResponse里面具体做了什么事
5.4 writeTransactionData
[IPCThreadState.cpp]
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
binder_transaction_data tr;
tr.target.ptr = 0;
tr.target.handle = handle;
tr.code = code;
tr.flags = binderFlags;
tr.cookie = 0;
tr.sender_pid = 0;
tr.sender_euid = 0;
//将数据用tr进行封装
...
//将数据写到mOut
mOut.writeInt32(cmd);
mOut.write(&tr, sizeof(tr));
return NO_ERROR;
}
显然,writeTransactionData主要的作用就是将要传递的参数写到mOut中去
5.5 waitForResponse
[IPCThreadState.cpp]
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
uint32_t cmd;
int32_t err;
while (1) {
if ((err=talkWithDriver()) < NO_ERROR) break;
...
//从Binder中读出数据
cmd = (uint32_t)mIn.readInt32();
//死循环加上switch,说明一次Binder交互会读出多次数据
switch (cmd) {
...
default:
//执行拿到的cmd
err = executeCommand(cmd);
if (err != NO_ERROR) goto finish;
break;
}
}
finish:
if (err != NO_ERROR) {
if (acquireResult) *acquireResult = err;
if (reply) reply->setError(err);
mLastError = err;
}
return err;
}
在waitForResponse中,会不断的从mIn中读出数据,然后根据这个读出的数据,执行不同的逻辑
六 总结
到此,我们基本知道了,MediaServer在使用Binder时,是如何注册的,不过对于IPCThreadState的细节,本篇还没完全说明白,关于后续的部分在下一篇说明