Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Binder机制来和客户端通讯交互的。所以搞明白Binder的话,在很大程度上就能理解程序运行的流程。
我们这里将以MediaService的例子来分析Binder的使用:
ServiceManager,这是Android OS的整个服务的管理程序
MediaService,这个程序里边注册了提供媒体播放的服务程序MediaPlayerService,我们最后只分析这个
MediaPlayerClient,这个是与MediaPlayerService交互的客户端程序
下面先讲讲MediaService应用程序。
MediaService是一个应用程序,虽然Android搞了七七八八的JAVA之类的东西,但是在本质上,它还是一个完整的Linux操作系统,也还没有牛到什么应用程序都是JAVA写。所以,MS(MediaService)就是一个和普通的C++应用程序一样的东西。
MediaService的源码文件在:framework\base\Media\MediaServer\Main_mediaserver.cpp中。让我们看看到底是个什么玩意儿!
<!-- lang: cpp -->
int main( int argc, char** argv )
{
/* FT,就这么简单?? */
/* 获得一个ProcessState实例 */
sp<ProcessState> proc( ProcessState::self() );
/* 得到一个ServiceManager对象 */
sp<IServiceManager> sm = defaultServiceManager();
MediaPlayerService::instantiate(); /* 初始化MediaPlayerService服务 */
ProcessState::self()->startThreadPool(); /*看名字,启动Process的线程池? */
IPCThreadState::self()->joinThreadPool(); /* 将自己加入到刚才的线程池? */
}
其中,我们只分析MediaPlayerService。
这么多疑问,看来我们只有一个个函数深入分析了。不过,这里先简单介绍下sp这个东西。
sp,究竟是smart pointer还是strong pointer呢?其实我后来发现不用太关注这个,就把它当做一个普通的指针看待,即sp ======》IServiceManager*吧。sp是google搞出来的为了方便C/C++程序员管理指针的分配和释放的一套方法,类似JAVA的什么WeakReference之类的。我个人觉得,要是自己写程序的话,不用这个东西也成。
好了,以后的分析中,sp 就看成是XXX*就可以了。
第一个调用的函数是ProcessState::self(),然后赋值给了proc变量,程序运行完,proc会自动delete内部的内容,所以就自动释放了先前分配的资源。
ProcessState位置在framework\base\libs\binder\ProcessState.cpp
<!-- lang: cpp -->
sp<ProcessState> ProcessState::self()
{
if ( gProcess != NULL )
return(gProcess); ---- >第 一 次进来肯定 走这 儿
AutoMutex _l( gProcessMutex ); --->锁 保护
if ( gProcess == NULL )
gProcess = new ProcessState; --->创 建 一 个 ProcessState对象
return(gProcess); --->看见没,这里返回的是指针, 但是函数返回的是sp<xxx>,所以把sp<xxx>看成是XXX*是可以的
}
再来看ProcessState构造函数
<!-- lang: cpp -->
/* 这个构造函数看来很重要 */
ProcessState::ProcessState()
: mDriverFD( open_driver() )----->Android很多代码都是这么写的,稍不留神就没看见这里调用了一个很重要的函数
, mVMStart( MAP_FAILED ) /*映射内存的起始地址 */
, mManagesContexts( false )
, mBinderContextCheckFunc( NULL )
, mBinderContextUserData( NULL )
, mThreadPoolStarted( false )
, mThreadPoolSeq( 1 )
{
if ( mDriverFD >= 0 )
{
/* BIDNER_VM_SIZE定义为(1*1024*1024) - (4096 *2) 1M-8K */
mVMStart = mmap( 0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE,
mDriverFD, 0 ); /* 这个需要你自己去man mmap的用法了,不过大概意思就是 */
/* 将fd映射为内存,这样内存的memcpy等操作就相当于write/read(fd)了 */
}
...
}
最讨厌这种在构造list中添加函数的写法了,常常疏忽某个变量的初始化是一个函数调用的结果。
open_driver
,就是打开/dev/binder这个设备,这个是android在内核中搞的一个专门用于完成进程间通讯而设置的一个虚拟的设备。BTW,说白了就是内核提供的一个机制,这个和我们用socket加NET_LINK方式和内核通讯是一个道理。
<!-- lang: cpp -->
static int open_driver()
{
int fd = open( "/dev/binder", O_RDWR ); /* 打开/dev/binder */
if ( fd >= 0 )
{
....
size_t maxThreads = 15;
/* 通过ioctl方式告诉内核,这个fd支持最大线程数是15个。 */
result = ioctl( fd, BINDER_SET_MAX_THREADS, &maxThreads );
}
return(fd);
}
好了,到这里Process::self就分析完了,到底干什么了呢?
打开/dev/binder设备,这样的话就相当于和内核binder机制有了交互的通道
映射fd到内存,设备的fd传进去后,估计这块内存是和binder设备共享的
接下来,就到调用defaultServiceManager()地方了。
defaultServiceManager
位置在framework\base\libs\binder\IServiceManager.cpp中
<!-- lang: cpp -->
sp<IServiceManager> defaultServiceManager()
{
if ( gDefaultServiceManager != NULL )
return(gDefaultServiceManager);
/* 又是一个单例,设计模式中叫 singleton。 */
{
AutoMutex _l( gDefaultServiceManagerLock );
if ( gDefaultServiceManager == NULL )
{
/* 真正的gDefaultServiceManager是在这里创建的喔 */
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject( NULL ) );
}
}
return(gDefaultServiceManager);
}
gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));
ProcessState::self
肯定返回的是刚才创建的gProcess,然后调用它的getContextObject
,注意,传进去的是NULL,即0。
<!-- lang: cpp -->
/* 回到ProcessState类, */
sp<IBinder> ProcessState::getContextObject( const sp<IBinder> & caller )
{
if ( supportsProcesses() ) /* 该函数根据打开设备是否成功来判断是否支持process */
{ /* 在真机上肯定走这个 */
return(getStrongProxyForHandle( 0 ) ); /* 注意,这里传入0 */
}
}
进入到getStrongProxyForHandle
,函数名字怪怪的,经常严重阻碍大脑运转。
注意这个参数的命名,handle
。搞过windows的应该比较熟悉这个名字,这是对资源的一种标示,其实说白了就是某个数据结构,保存在数组中,然后handle是它在这个数组中的索引。—>就是这么一个玩意儿
<!-- lang: cpp -->
sp<IBinder> ProcessState::getStrongProxyForHandle( int32_t handle )
{
sp<IBinder> result;
AutoMutex _l( mLock );
handle_entry* e = lookupHandleLocked( handle ); --哈哈,果然,从数组中查找对应索引的资源 。
//lookupHandleLocked这个就不说了,内部会返回一个handle_entry
/*
*
* struct handle_entry {
*
* IBinder* binder;--->Binder
*
* RefBase::weakref_type* refs;-->不知道是什么,不影响.
*
* };
*
*/
if ( e != NULL )
{
IBinder* b = e->binder; -- > 第一次进来,肯定为空
if ( b == NULL || !e->refs->attemptIncWeak( this ) )
{
b = new BpBinder( handle ); --->看见了吧,创建了一个新的BpBinder
e->binder = b;
result = b;
}
....
}
return(result); --->返回刚才创建的BpBinder
}
到这里,是不是有点乱了?对,当人脑分析的函数调用太深的时候,就容易忘记。
我们是从gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));
开始搞的,现在,这个函数调用将变成gDefaultServiceManager = interface_cast<IServiceManager>(new BpBinder(0));
BpBinder又是个什么玩意儿?Android名字起得太眼花缭乱了。
因为还没介绍Binder机制的大架构,所以这里介绍BpBinder不合适,但是又讲到BpBinder了,不介绍Binder架构似乎又说不清楚….,sigh!
恩,还是继续把层层深入的函数调用栈化繁为简吧,至少大脑还可以工作。先看看BpBinder的构造函数吧。
BpBinder位置在framework\base\libs\binder\BpBinder.cpp中。
<!-- lang: cpp -->
BpBinder::BpBinder( int32_t handle )
: mHandle( handle ) /* 注意,接上述内容,这里调用的时候传入的是0 */
, mAlive( 1 )
, mObitsSent( 0 )
, mObituaries( NULL )
{
IPCThreadState::self()->incWeakHandle( handle ); /* FT,竟然到IPCThreadState::self() */
}
这里一块说说吧。IPCThreadState::self
估计怎么着又是 一 个 singleton 吧 ?
<!-- lang: cpp -->
/* 该文件位置在framework\base\libs\binder\IPCThreadState.cpp */
IPCThreadState* IPCThreadState::self()
{
if ( gHaveTLS ) /* 第一次进来为false */
{
restart:
const pthread_key_t k = gTLS;
/* TLS是Thread Local Storage的意思,不懂得自己去google下它的作用吧。这里只需要 */
/* 知道这种空间每个线程有一个,而且线程间不共享这些空间,好处是?我就不用去搞什么 */
/*同步了。在这个线程,我就用这个线程的东西,反正别的线程获取不到其他线程TLS中的数据。===》这句话有漏洞,钻牛角尖的明白大概意思就可以了。 */
/* 从线程本地存储空间中获得保存在其中的IPCThreadState对象 */
/* 这段代码写法很晦涩,看见没,只有pthread_getspecific,那么肯定有地方调用 */
/* pthread_setspecific。 */
IPCThreadState* st = (IPCThreadState *) pthread_getspecific( k );
if ( st )
return(st);
return(new IPCThreadState); /* new一个对象, */
}
if ( gShutdown )
return(NULL);
pthread_mutex_lock( &gTLSMutex );
if ( !gHaveTLS )
{
if ( pthread_key_create( &gTLS, threadDestructor ) != 0 )
{
pthread_mutex_unlock( &gTLSMutex );
return(NULL);
}
gHaveTLS = true;
}
pthread_mutex_unlock( &gTLSMutex );
goto restart; /* 我FT,其实goto没有我们说得那样卑鄙,汇编代码很多跳转语句的。 */
/* 关键是要用好。 */
}
/* 这里是构造函数,在构造函数里边pthread_setspecific */
IPCThreadState::IPCThreadState()
: mProcess( ProcessState::self() ), mMyThreadId( androidGetTid() )
{
pthread_setspecific( gTLS, this );
clearCaller();
mIn.setDataCapacity( 256 );
/* mIn,mOut是两个Parcel,干嘛用的啊?把它看成是命令的buffer吧。再深入解释,又会大脑停摆的。 */
mOut.setDataCapacity( 256 );
}
出来了,终于出来了….,恩,回到BpBinder那。
<!-- lang: cpp -->
BpBinder::BpBinder(int32_t handle)
: mHandle(handle) //注意,接上述内容,这里调用的时候传入的是0
, mAlive(1)
, mObitsSent(0)
, mObituaries(NULL)
{
......
IPCThreadState::self()->incWeakHandle(handle);
/**什么incWeakHandle,不讲了..**/
}
喔,new BpBinder就算完了。到这里,我们创建了些什么呢?
ProcessState有了。
IPCThreadState有了,而且是主线程的。
BpBinder有了,内部handle值为0。
gDefaultServiceManager = interface_cast<IServiceManager>(new BpBinder(0));
终于回到原点了,大家是不是快疯掉了?
interface_cast
,我第一次接触的时候,把它看做类似的static_cast一样的东西,然后死活也搞不明白 BpBinder指针怎么能强转为IServiceManager,花了n多时间查看BpBinder是否和IServiceManager继承还是咋的….。
终于,我用ctrl+鼠标(source insight)跟踪进入了interface_cast
IInterface.h位于framework/base/include/binder/IInterface.h
<!-- lang: cpp -->
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
所以,上面等价于:
<!-- lang: cpp -->
inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj)
{
return IServiceManager::asInterface(obj);
}
看来,只能跟到IServiceManager了。
IServiceManager.h—》framework/base/include/binder/IServiceManager.h
看看它是如何定义的:
<!-- lang: cpp -->
class IServiceManager : public IInterface
{
//ServiceManager,字面上理解就是Service管理类,管理什么?增加服务,查询服务等
//这里仅列出增加服务addService函数
public:
DECLARE_META_INTERFACE(ServiceManager);
virtual status_t addService( const String16& name,
const sp<IBinder>& service) = 0;
};
DECLARE_META_INTERFACE(ServiceManager)??
怎么和MFC这么类似?微软的影响很大啊!知道MFC的,有DELCARE肯定有IMPLEMENT。
果然,这两个宏DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE(INTERFACE, NAME)都在刚才的IInterface.h中定义。我们先看看DECLARE_META_INTERFACE这个宏往IServiceManager加了什么?
下面是DECLARE宏
<!-- lang: cpp -->
#define DECLARE_META_INTERFACE(INTERFACE) \
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();
我们把它兑现到IServiceManager就是:
static const android::String16 descriptor;
–>喔,增加一个描述字符串
`static android::sp< IServiceManager > asInterface(const android::sp &
obj)` —>增加一个asInterface函数
virtual const android::String16& getInterfaceDescriptor() const;
—>增加一个get函数
估计其返回值就是descriptor这个字符串
IServiceManager (); \
virtual ~IServiceManager(); \**增加构造和虚析购函数...**\
那IMPLEMENT宏在哪定义的呢?
见IServiceManager.cpp。位于framework/base/libs/binder/IServiceManager.cpp
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
下面是这个宏的定义
<!-- lang: cpp -->
#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<I##INTERFACE> I##INTERFACE::asInterface( \
const android::sp<android::IBinder>& obj) \
{ \
android::sp<I##INTERFACE> intr; \
if (obj != NULL) { \
intr = static_cast<I##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() { } \
很麻烦吧?尤其是宏看着头疼。赶紧兑现下吧。
<!-- lang: cpp -->
const
android::String16 IServiceManager::descriptor(“android.os.IServiceManager”);
const android::String16& IServiceManager::getInterfaceDescriptor() const
{ return IServiceManager::descriptor;//返回上面那个android.os.IServiceManager
} android::sp<IServiceManager> IServiceManager::asInterface(
const android::sp<android::IBinder>& obj)
{
android::sp<IServiceManager> intr;
if (obj != NULL) {
intr = static_cast<IServiceManager *>(
obj->queryLocalInterface(IServiceManager::descriptor).get());
if (intr == NULL) {
intr = new BpServiceManager(obj);
}
}
return intr;
}
IServiceManager::IServiceManager () { }
IServiceManager::~ IServiceManager() { }
哇塞,asInterface是这么搞的啊,赶紧分析下吧,还是不知道interface_cast怎么把BpBinder*转成了IServiceManager
我们刚才解析过的interface_cast (new BpBinder(0)),
原来就是调用asInterface(new BpBinder(0))
<!-- lang: cpp -->
android::sp<IServiceManager> IServiceManager::asInterface(
const android::sp<android::IBinder>& obj)
{
android::sp<IServiceManager> intr;
if (obj != NULL) {
....
intr = new BpServiceManager(obj);
//神呐,终于看到和IServiceManager相关的东西了,看来
//实际返回的是BpServiceManager(new BpBinder(0));
}
}
return intr;
}
BpServiceManager是个什么玩意儿?p是什么个意思?
终于可以讲解点架构上的东西了。p是proxy即代理的意思,Bp就是BinderProxy,BpServiceManager,就是SM的Binder代理。既然是代理,那肯定希望对用户是透明的,那就是说头文件里边不会有这个Bp的定义。是吗?
果然,BpServiceManager就在刚才的IServiceManager.cpp中定义。
<!-- lang: cpp -->
class BpServiceManager : public BpInterface<IServiceManager>
//这种继承方式,表示同时继承BpInterface和IServiceManager,这样IServiceManger的addService必然在这个类中实现
{
public:
//注意构造函数参数的命名 impl,难道这里使用了Bridge模式?真正完成操作的是impl对象?
//这里传入的impl就是new BpBinder(0)
BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
{
}
virtual status_t addService(const String16& name, const sp<IBinder>& service)
{
//待会再说..
}
//基类BpInterface的构造函数(经过兑现后)
//这里的参数又叫remote,唉,真是害人不浅啊。
inline BpInterface< IServiceManager >::BpInterface(const sp<IBinder>& remote)
: BpRefBase(remote)
{
}
BpRefBase::BpRefBase(const sp<IBinder>& o)
: mRemote(o.get()), mRefs(NULL), mState(0)
//o.get(),这个是sp类的获取实际数据指针的一个方法,你只要知道
//它返回的是sp<xxxx>中xxx* 指针就行
{
//mRemote就是刚才的BpBinder(0)
...
}
好了,到这里,我们知道了:
sp<IServiceManager> sm = defaultServiceManager();
返回的实际是BpServiceManager,它的remote对象是BpBinder,传入的那个handle参数是0。
现在重新回到MediaService。
<!-- lang: cpp -->
int main(int argc, char** argv)
{
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
//上面的讲解已经完了
MediaPlayerService::instantiate();//实例化MediaPlayerservice
//看来这里有名堂!
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
到这里,我们把binder设备打开了,得到一个BpServiceManager对象,这表明我们可以和SM打交道了,但是好像没干什么有意义的事情吧?
(未完待续…)