前一篇博客中,我们分析了Binder通信的架构,以及其中作为服务管理者的ServiceManager的主要作用。
在这一篇博客中,我们主要来分析一下,一个普通的服务如何使用Binder通信,将自己注册到ServiceManager中。
我们选择从MediaServer进程入手,来分析整个服务注册过程。
之所以选择从这个进程开始分析,是因为在《深入理解Android 卷I》中,邓凡平前辈讲解过这个进程。对比前辈的分析和实际的代码,应该可以更快地完成知识的迭代。
在Android7.0中,MediaServer进程对应的代码定义于frameworks/av/media/mediaserver目录下。
mediaserver.rc中的定义如下:
service media /system/bin/mediaserver
class main
user media
group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
ioprio rt 4
writepid /dev/cpuset/foreground/tasks
从rc文件,可以看出mediaserver进程的class为main,因此它的启动时间应该在ServiceManager进程之后。当mediaserver进程被init进程加载后,将调用该进程对应的main函数。
main函数定义于main_mediaserver.cpp中:
int main()
{
//看网上的资料,当服务器端关闭一个连接后,客户端仍不断向服务器发送数据时,系统将产生一个SIGPIPE信号给客户端进程,告知它不要再发送数据了
//收到SIGPIPE信号后,默认行为是关闭进程;在这里忽略了SIGPIPE信号
//mediaserver作为servicemanager的客户端,那么推测这里应该是针对servicemanager异常断开连接的处理
signal(SIGPIPE, SIG_IGN);
//获得ProcessState实例
sp<ProcessState> proc(ProcessState::self());
//获取与ServiceManager交互的代理对象
sp<IServiceManager> sm = defaultServiceManager();
.......................
//注册服务
MediaPlayerService::instantiate();
........................
//创建线程池
ProcessState::self()->startThreadPool();
//加入线程池
IPCThreadState::self()->joinThreadPool();
}
1 获取ProcessState
在main函数的开始,获取了ProcessState对象。每个进程只有一个ProcessState对象:
sp<ProcessState> ProcessState::self() {
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
gProcess = new ProcessState;
return gProcess;
}
从上面的代码可以看出,self通过单例的方式构造出ProcessState。
我们看看ProcessState的构造函数:
ProcessState::ProcessState()
//open_driver将开启binder设备
: mDriverFD(open_driver())
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mStarvationStartTimeMs(0)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
//打开Binder驱动成功后
if (mDriverFD >= 0) {
//为Binder驱动分配地址接收数据,完成内核空间和用户空间地址的映射
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
...........
close(mDriverFD);
mDriverFD = -1;
}
}
..............
}
我们看看open_driver函数:
static int open_driver() {
//打开Binder设备
int fd = open("/dev/binder", O_RDWR | O_CLOEXEC);
if (fd >= 0) {
//检查用户空间和内核空间版本是否一致
.....
//DEFAULT_MAX_BINDER_THREADS值为15
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
//设置该fd支持最大线程数为15
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
................
}
}
至此,ProcessState::self函数的主要流程就结束了。
从上面的代码我们知道:
进程通过创建ProcessState来打开Binder设备;
内核的Binder驱动会为进程分配对应的内存以接收数据;
每个进程最多同时为15个客户端提供服务。
2 调用defaultServiceManager得到ServiceManager的代理
在创建为ProcessState后,main函数调用了defaultServiceManager函数。
defaultServiceManager函数定义于IServiceManager.cpp中:
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
//不断尝试获取IServiceManager
while (gDefaultServiceManager == NULL) {
//实际的创建
gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));
if (gDefaultServiceManager == NULL)
sleep(1);
}
}
return gDefaultServiceManager;
}
2.1 创建BpBinder
从上面的代码,可以看出defaultServiceManager是通过ProcessState::self()->getContextObject(NULL)来获取通信实体的。
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/) {
//注意此处的参数
return getStrongProxyForHandle(0);
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) {
sp<IBinder> result;
AutoMutex _l(mLock);
//ProcessState中维持了一个资源数组(实际为Vector): mHandleToObject, handle是获取具体资源的索引
//lookupHandleLocked将按照索引查找对应的资源,如果没有发现对应的资源项,将创建一个新的资源项并返回
//新创建的资源项的索引就是handle,并且内容处于待填充的状态
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
IBinder* b = e->binder;
//填充新创建的资源
if (b == NULL || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
//如果是创建与ServiceManager通信的对象,则先利用IPC通信向ServiceManager发送PING_TRANSACTION消息
//通过返回值,判断ServiceManager是否正常存活;在ServiceManager的svcmgr_handler中,收到PING_TRANSACTION后,返回0
Parcel data;
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
retun NULL;
}
//利用handle创建一个BpBinder
b = new BpBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
.........
}
}
//返回BpBinder
return result;
}
在进一步分析之前,我们需要先需要了解一下BpBinder和BBinder。这里我们借鉴一下《深入理解Android 卷I》中的叙述:
Android中定义了BpBinder和BBinder,它们是Binder通信相关的代表,都是从IBinder类中派生而来。
BpBinder是客户端用来与Server交互的代理类;BBinder则代表了服务端。BpBinder与BBinder是一一对应的,即某个BpBinder只能与对应的BBinder交互。
在上文的代码中,MediaServer进程与ServerManager进程通信。
MediaServer进程是ServiceManager进程的客户端,因此在该Binder通信的连接中,MediaServer进程需要获取BpBinder对象。
从代码可以看出,Android使用handle来创建BpBinder,handle就是用来标识与该BpBinder通信的BBinder的。
2.2 构建出BpServiceManager
我们回到defaultServiceManager函数,在利用ProcessState创建出BpBinder后,代码可以转化为:
..........
gDefaultServiceManager = interface_cast(new BpBinder(0));
..........
上述代码中,interface_cast为定义于IInterface.h中的模板:
template<typename INTERFACE>
inline sp interface_cast(const sp& obj)
{
return INTERFACE::asInterface(obj);
}
因此上述代码可以被转化为:
gDefaultServiceManager = IServiceManager::asInterface(new BpBinder(0));
接下来我们需要看一下IServiceManager中定义的asInterface函数了。
先观察一下IServiceManager.h:
class IServiceManager : public IInterface
{
public:
//IInterface中的宏定义
DECLARE_META_INTERFACE(ServiceManager);
//下面定义了服务接口
...............
}
IInterface中的宏定义如下:
#define DECLARE_META_INTERFACE(INTERFACE) \
static const android::String16 descriptor; \
static android::sp##INTERFACE> asInterface( \
const android::sp& obj); \
virtual const android::String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE();
根据宏定义,可以看IServiceManager中确实定义了接口:
static android::sp asInterface(const android::sp::IBinder>& obj);
该函数的实现在IServiceManager.cpp中:
//BpServiceManager继承BpInterface,后者继承IServiceManager,负责实现业务接口
class BpServiceManager : public BpInterface<IServiceManager> {
..........
}
//IInterface中的宏定义
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
对应的宏定义如下:
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
const android::String16 I##INTERFACE::descriptor(NAME); \
const android::String16& \
I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
} \
android::sp##INTERFACE> I##INTERFACE::asInterface( \
const android::sp& obj) \
{ \
android::sp##INTERFACE> intr; \
if (obj != NULL) { \
intr = static_cast##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == NULL) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { } \
从上面的宏定义可以看出,最终defaultServiceManager中的代码可以被转化为:
gDefaultServiceManager = new BpServiceManger(new BpBinder(0));
上面已经提到,BpServiceManger定义于IServiceManger.cpp中,实现了IServiceManager.h定义的业务接口。
因此我们知道,调用defaultServiceManager的目的是:得到ServiceManager进程的服务代理对象。
该代理对象的接口与真实服务提供者的接口一样。
BpServiceManager作为服务代理对象,就是靠之前创建的BpBinder(0)来与实际的服务对象通信的,现在看看它的构造函数:
BpServiceManager(const sp& impl)
: BpInterface(impl)
{
}
进一步追踪到BpInterface:
templateINTERFACE>
class BpInterface : public INTERFACE, public BpRefBase {
..........
}
templateINTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp& remote)
: BpRefBase(remote)
{
}
从上面的代码可以看出,BpBinder(0)最终传入了BpRefBase。
BpRefBase::BpRefBase(const sp<IBinder>& o)
: mRemote(o.get()), mRefs(NULL), mState(0)
{
........
}
最终,BpRefBase中的mRemote对象持有了BpBinder(0)。
当用户调用BpServiceManager中的接口时,BpServiceManager利用mRemote对象将请求发往实际ServiceManager进程。
以上过程看起来比较混乱,我们来看看这部分流程涉及的对象之间的关系,大致上就能体会Android的设计初衷:
如上图所示,不同颜色的类代表了不同的设计意图。
注意实际的代码中,并不存在BnServiceManager和RealServiceManager这两个类,因为ServiceManager进程可以直接与Binder驱动通信,不需要依赖这一套继承体系。
这里只是将ServiceManger当做一个普通的服务提供进程,以便说明Android中一般情况下的Binder通信架构。
Tip1、图中绿色部分,为实际业务对应的类。IServiceManager中定义了服务应提供的实际接口,客户端进程中的BpServiceManger和服务端进程中的BnServiceManager均需要实现IServiceManager中定义的接口。RealServiceManager继承BnServiceManger,可以实现一些不依赖于Binder通信的方法。
Tip2、IInterface类实际上主要通过宏定义,起到转换的作用。
例如:其子类IServiceManager通过宏可以利用BpBinder构成BpServiceManager。
也就是说通过IInterface的继承体系,其子类可以利用BpBinder和BBinder构成满足实际业务要求的接口。
Tip3、BpInterface和BnInterface其实就是为了连接业务类和Binder类。不同的是BpInterface通过继承BpRefBase来持有一个BpBinder对象,而BnInterface是通过继承的方式来成为一个BBinder对象。
Tip4、RefBase的继承体系其实与Binder通信并没有实际的关联性,应该是用于管理对象引用的情况,与内存管理有关。
Tip5、BpBinder和BBinder继承自IBinder接口,实现与Binder驱动交互的接口。
通过上述的继承体系,我们可以看到Android将实际业务的继承体系,与Binder的继承体系分离开来。通过定义与业务相关的IServiceManger、BpServiceManger等类,以及IInterface体系提供的转换关系,就将实际业务的传输架构在Binder体系之上了。
3 注册服务
我们再次回到MediaServer的main函数,在调用defaultServiceManger获取到BpServiceManger对象后,MediaServer进程调用MediaPlayerService::instantiate(),将MediaPlayerService注册到ServiceManager中。
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
}
我们看看BpServiceManager中的addService函数:
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated)
{
//将信息打包到data中,reply负责接受返回结果
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
//remote实际为BpBinder
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
//判断返回结果是否OK
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
BpBinder中的transact函数:
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) {
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
从上面的代码可以看出,对于Binder通信来说,传输工作的实际操作者为IPCThreadState,因此我们需要进一步分析一下IPCThreadState。
3.1 IPCThreadState的构造
IPCThreadState* IPCThreadState::self()
{
//初始时gHaveTLS为false
if (gHaveTLS) {
restart:
const pthread_key_t k = gTLS;
//TLS是Thread Local Storage(线程本地存储空间)的简称
//pthread_getspecific可以获取TLS中存储的数据
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
if (st) return st;
//第一次时,下面创建出gTLS后,调用IPCThreadState的构造函数
return new IPCThreadState;
}
if (gShutdown) {
ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
return NULL;
}
pthread_mutex_lock(&gTLSMutex);
if (!gHaveTLS) {
//第一次进入时,创建出存储IPCThreadState对象的key值gTLS
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 NULL;
}
gHaveTLS = true;
}
pthread_mutex_unlock(&gTLSMutex);
goto restart;
}
现在看一下IPCThreadState的构造函数:
IPCThreadState::IPCThreadState()
: mProcess(ProcessState::self()),
mMyThreadId(gettid()),
mStrictModePolicy(0),
mLastTransactionBinderFlags(0)
{
//利用pthread_setspecific将自己存储到TLS中
pthread_setspecific(gTLS, this);
clearCaller();
//mIn用来接收Binder设备的数据
//mOut用来向Binder设备发送数据
mIn.setDataCapacity(256);
mOut.setDataCapacity(256);
}
3.2 IPCThreadState的传输工作
创建出IPCThreadState后,将调用其transact函数进行实际的传输工作:
//注意handle为目的端句柄,在此流程中为0
//code为本次传输的消息码,即定义此次消息的目的,在此流程中为ADD_SERVICE_TRANSACTION
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
//检查数据的有效性
status_t err = data.errorCheck();
..........
if (err == NO_ERROR) {
//发送数据
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
}
if (err != NO_ERROR) {
if (reply) reply->setError(err);
return (mLastError = err);
}
//flags默认为0
if ((flags & TF_ONE_WAY) == 0) {
..................
if (reply) {
//等待结果
err = waitForResponse(reply);
} else {
...........
}
................
} else {
........
}
return err;
}
跟进writeTransactionData:
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; /* Don't pass uninitialized stack data to a remote process */
//handle传递给target,用以标识目的端,此处传递的值为0
tr.target.handle = handle;
tr.code = code;
tr.flags = binderFlags;
tr.cookie = 0;
tr.sender_pid = 0;
tr.sender_euid = 0;
//检查将传数据的正确性
const status_t err = data.errorCheck();
if (err == NO_ERROR) {
//正常情况下,将数据填入到binder_transaction_data结构体中
tr.data_size = data.ipcDataSize();
tr.data.ptr.buffer = data.ipcData();
tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
tr.data.ptr.offsets = data.ipcObjects();
} else if (statusBuffer) {
//这里是构造包含错误信息的结构体
//在此流程中,statusBuffer为null
........
} else {
return (mLastError = err);
}
//注意此处只是将待发送数据写入到mOut缓冲中
mOut.writeInt32(cmd);
mOut.write(&tr, sizeof(tr));
return NO_ERROR;
}
再看一下waitForResponse函数:
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
uint32_t cmd;
int32_t err;
while (1) {
//talkWithDriver中,将进行实际的发送
if ((err=talkWithDriver()) < NO_ERROR) break;
//判断回复信息是否正确,是否需要处理
err = mIn.errorCheck();
if (err < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
cmd = (uint32_t)mIn.readInt32();
............
switch (cmd) {
case BR_TRANSACTION_COMPLETE:
if (!reply && !acquireResult) goto finish;
.........
case BR_REPLY:
//若有回复消息,处理完后才结束
.........
goto finish;
default:
//处理收到的数据,以后再分析
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;
}
我们看看talkWithDriver函数:
//参数默认为true
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
..........
//bwr为与binder设备交换数据的结构
binder_write_read bwr;
// Is the read buffer empty?
const bool needRead = mIn.dataPosition() >= mIn.dataSize();
// We don't want to write anything if we are still reading
// from data left in the input buffer and the caller
// has requested to read the next data.
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
//将待发送的数据写入到bwr中
//按上面的注释,当有数据要读取时,此次不写入数据
bwr.write_size = outAvail;
bwr.write_buffer = (uintptr_t)mOut.data();
if (doReceive && needRead) {
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (uintptr_t)mIn.data();
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
................
// Return immediately if there is nothing to do.
if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
...............
do {
................
#if defined(__ANDROID__)
//通过ioctl的方式与binder设备通信,读取数据到bwr中或将bwr中的数据写到binder设备中
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
else
err = -errno;
#else
err = INVALID_OPERATION;
#endif
if (mProcess->mDriverFD <= 0) {
err = -EBADF;
}
...............
} while (err == -EINTR);
....................
}
至此MediaServicePlayer的注册过程就结束了。结合之前博客分析ServiceManager的流程,我们知道svcmgr_handler收到消息后,会利用MediaServicePlayer对应信息构建出service info加入到svclist中。
4 startThreadPool和joinThreadPool
从前面的代码,我们看到MediaServer进程已经开启了Binder设备,同时将一些重要的服务注册到ServiceManager中。
在main函数的最后,MediaServer还调用了ProcessState::self()->startThreadPool和IPCThreadState::self()->joinThreadPool,我们现在看看这么做到底有什么用处。
4.1 startThreadPool
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName();
ALOGV("Spawning new pooled thread, name=%s\n", name.string());
//创建了一个PoolThread,然后运行;此处参数为true
sp<Thread> t = new PoolThread(isMain);
t->run(name.string());
}
}
看看PoolThread类的定义:
class PoolThread : public Thread
{
public:
PoolThread(bool isMain)
: mIsMain(isMain)
{
}
protected:
virtual bool threadLoop()
{
//注意这里又调用了一次IPCThreadState::self()
//由于IPCThreadState每个线程一个
//因此MediaServer进程调用startThreadPool后,共有两个IPCThreadState;主线程和poolThread各有一个
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
const bool mIsMain;
};
4.2 joinThreadPool
注意在主线程和PoolThread中的IPCThreadState,均调用了joinThreadPool函数(默认参数就是true),且传入参数均为true。
void IPCThreadState::joinThreadPool(bool isMain)
{
...............
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
...............
status_t result;
do {
//处理已经死亡的BBinder对象
processPendingDerefs();
//发送命令和读取请求
result = getAndExecuteCommand();
//根据result的结果,判断是否异常退出
..............
} while (result != -ECONNREFUSED && result != -EBADF);
...............
//异常退出循环
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
现在跟进getAndExecuteCommand:
status_t IPCThreadState::getAndExecuteCommand()
{
........
//前面已经提过,通过ioctl与binder设备通信,写入命令,读取请求
result = talkWithDriver();
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
..........
cmd = mIn.readInt32();
..........
//处理收到的消息
result = executeCommand(cmd);
..........
}
return result;
}
现在我们明白了,MediaServer进程中,主线程和子线程的IPCThreadState调用joinThreadPool后,都会通过talkWithDriver向Binder设备发送消息,并接收和处理Binder设备返回的命令。
结束语
本篇博客以MediaServer进程为例,分析一个普通的服务进程如何使用Binder通信机制,包括开启Binder设备、向ServiceManager进程注册自己及利用IPCThreadState来与Binder设备通信。
其实Binder通信机制并不复杂,只是Android中将实际业务和Binder通信机制整合在了一起,看起来不太直观。了解整个继承结构和原理后,Binder通信就没有什么神秘的。
上图中左边为基于Binder通信的业务架构;右边为替换成socket的业务架构。容易看出Binder就是一种通信机制。