文档章节

Android深入浅出之Binder机制(一)

ifindbug
 ifindbug
发布于 2014/09/25 23:23
字数 3247
阅读 73
收藏 1

一、 说明

Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Binder机制来和客户端通讯交互的。所以搞明白Binder的话,在很大程度上就能理解程序运行的流程。

我们这里将以MediaService的例子来分析Binder的使用:

  • ServiceManager,这是Android OS的整个服务的管理程序

  • MediaService,这个程序里边注册了提供媒体播放的服务程序MediaPlayerService,我们最后只分析这个

  • MediaPlayerClient,这个是与MediaPlayerService交互的客户端程序

下面先讲讲MediaService应用程序。

二、 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>======》IServiceManager*吧。sp是google搞出来的为了方便C/C++程序员管理指针的分配和释放的一套方法,类似JAVA的什么WeakReference之类的。我个人觉得,要是自己写程序的话,不用这个东西也成。

好了,以后的分析中,sp<XXX>就看成是XXX*就可以了。

2.1 ProcessState

第一个调用的函数是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)了 */
	}

	...
}

<font color="red">最讨厌这种在构造list中添加函数的写法了,常常疏忽某个变量的初始化是一个函数调用的结果。</font>

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()地方了。

2.2 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的构造函数吧。

2.3 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

看看它是如何定义的:

2.4 IServiceManager

<!-- 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::spandroid::IBinder&

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<IServiceManager>(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是什么个意思?

2.5 BpServiceManager

终于可以讲解点架构上的东西了。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打交道了,但是好像没干什么有意义的事情吧?

(未完待续...)

本文转载自:http://www.cnblogs.com/innost/archive/2011/01/09/1931456.html

共有 人打赏支持
ifindbug
粉丝 0
博文 9
码字总数 0
作品 0
广州
私信 提问
Android深入浅出之Binder机制

Android深入浅出之Binder机制 一 说明 Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Binder机制来和客户端通讯交互的。所以搞明白Binder的话,在很大程度...

z.net
2013/06/25
0
0
Android深入浅出之Binder机制

Android深入浅出之Binder机制 一说明 Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Binder机制来和客户端通讯交互的。所以搞明白Binder的话,在很大程度...

陈wei
2013/03/13
0
0
Android系统的Binder机制之一——Service Manager

Android虽然构建在Linux上面,但是在IPC(进程间)机制方面,没有利用Linux提供IPC机制,而是自己实现了一套轻量级的IPC机制——binder机制。并且Android Binder机制之上,Android框架提供了...

垂盆草
2012/08/04
0
0
Android系统的Binder机制之二——服务代理对象(1)

上文《Android系统的Binder机制之一——Service Manager》我们学习了Service Manager在Android Binder中的作用——服务(Service)注册,服务(Service)查询的功能。本文我们一起学习服务(...

垂盆草
2012/08/04
0
0
Android AIDL浅析及异步调用

AIDL:Android Interface Definition Language,即 Android 接口定义语言。 AIDL 是什么 Android 系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。 为了使其...

cspecialy
05/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

关于《红楼梦》的读后感优秀范文2000字

关于《红楼梦》的读后感优秀范文2000字: (在写读《红楼梦》有感的路上遇到了博友“五音不全”师兄,使我感到汗颜,于是放弃了87版的电视剧,只读原著《红楼梦》和五音的评红作品,对原著才...

原创小博客
13分钟前
0
0
cookie与session详解

session与cookie是什么? session与cookie属于一种会话控制技术.常用在身份识别,登录验证,数据传输等.举个例子,就像我们去超市买东西结账的时候,我们要拿出我们的会员卡才会获取优惠.这时...

士兵7
16分钟前
0
0
十万个为什么之为什么大家都说dubbo

Dubbo是什么? 使用背景 dubbo为什么这么流行, 为什么大家都这么喜欢用dubbo; 通过了解分布式开发了解到, 为适应访问量暴增,业务拆分后, 子应用部署在多台服务器上,而多台服务器通过可以通过d...

尾生
今天
2
0
Docker搭建代码质量检测平台-SonarQube(中文版)

Sonar是一个用于代码质量管理的开源平台,用于管理源代码的质量,可以从七个维度检测代码质量。通过插件形式,可以支持包括java,C#,C/C++,PL/SQL,Cobol,JavaScrip,Groovy等等二十几种编程语言...

Jacktanger
今天
2
0
Windows / Linux / MacOS 设置代理上网的方法汇总

本文汇总了 Windows / Linux / MacOS 设置代理上网的各种方法,总结如下: 1、设置系统代理(Windows、Linux、MacOS) 2、设置代理插件(Chrome、Chromium、Firefox、Opera、QQ等浏览器) 3、...

sunboy2050
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部