Android系统进程间通信Binder机制在低层的C++接口源代码文件分析

-----------------------------------------重点在BpServiceManager和BpBinder(0)-------------------------------------

1、

RefBase.cpp

RefBase.h

定义了如下几个类:

一、class

RefBase{}

定义了所有类的基类,他应该是一个普遍基类,并不是一个抽象类。

二、

template

class sp{}

模板智能指针sp,是binder系统中最常用的类型,用来执行具体的类型变量,

类内使用

T*m_ptr;

存储指向类型对象的指针。

使用

inlineT*get() const{ return m_ptr; }

get函数获取指向的对象。

三、

template

class wp{}

2、

IBinder.h

Binder.cpp

只实现一个类,

class IBinder : public virtual RefBase{}

注意继承自RefBase,并且指定为虚基类,防止“二义性”。

这是Binder最重要的一个低层类,上层所有Binder类型都是继承自它。

他是一个抽象类,除了几个重要虚函数外,其他的都是纯虚函数。

几个重要的虚函数如下所示,

spIBinder::queryLocalInterface(const String16&descriptor)----后续可以用来查询派生类的IInterface

BBinder* IBinder::localBinder()----返回一个本地的Binder对象--BBinder

BpBinder* IBinder::remoteBinder()----返回一个代理的Binder对象--BpBinder

bool IBinder::checkSubclass(const void*

/*subclassID*/) const----检查派生类

3、

Binder.h

Binder.cpp

实现两个类,如下所示:

一、class

BBinder : public IBinder{}

这个类public继承自IBinder,用来实现Binder的本地对象。注意它在private部分声明了

BBinder&operator=(const BBinder& o);

说明这个类对象不能使用operator=进行赋值操作,即对operator=放到了private区,进行了隐藏。

另外,此类对其基类IBinder的所有纯虚函数进行了实现,因此此类可以创建对象,不是一个抽线类。

二、class

BpRefBase : public virtual RefBase{}

这个类应该是最深基类RefBase的一个“代理”,它也是一个“虚基类”,防止后续派生类产生“二义性”

因为是代理,它有一个重要的private成员,

IBinder* constmRemote;

IBinder指针,指向远程的IBinder对象。

使用函数,

inlineIBinder*remote(){ return mRemote; }

来获取。

另外,在private区,有如下定义,

BpRefBase&operator=(const BpRefBase&o);

对operator=进行了隐藏,说明此类对象不支持赋值操作。

private区还有一个变量,

RefBase::weakref_type*mRefs;

目前不知道做什么用的。

4、

BpBinder.h

BpBinder.cpp

class BpBinder : public IBinder{}

这个类是一个重要的类,用它来实现和其他service的交互。public继承自IBinder,用来实现Binder的代理对象。

定义了一个重要的函数,

virtual BpBinder*remoteBinder();

用来返回它自身。

注意函数defaultServiceManager中,

sp b =

ProcessState::self()->getContextObject(NULL);

相当于,

sp b = new BpBinder(0);

注意此类中的成员变量mHandle保存有Binder设备ID,永远为0。

5、

IInterface.h

IInterface.cpp

主要实现如下几个类:

一、class

IInterface : public virtual RefBase{}

所有类的一个公共接口,他是一个抽象类,只能用作继承。注意它使用了virtual继承RefBase,因此它成为“虚基类”,防止后续类再继承它时产生“二义性”。

此类注意onAsBinder是一个纯虚函数,后续的派生类都需要有一个实现,他的返回值为IBinder。

二、template

INTERFACE>

class BnInterface : public INTERFACE,

public BBinder

模板类BnInterface,除了继承模板指定的类外,还继承了BBinder。

有三个重要的虚基类,

virtual spqueryLocalInterface(const String16&_descriptor);

virtual const String16&getInterfaceDescriptor() const;

virtual IBinder*onAsBinder();

其中onAsBinder继承了基类IInterface的纯虚函数。

三、template

INTERFACE>

class BpInterface : public INTERFACE,

public BpRefBase

模板类BpInterface,除了继承模板指定的类外,还继承了代理类BpRefBase。

BpInterface是BnInterface的代理,声明一个重要函数

virtual IBinder*onAsBinder();

6、

IServiceManager.h

IServiceManager.cpp

主要实现如下几个类:

一、

class IServiceManager : public IInterface{}

继承自抽象类IInterface,自身也是抽象类,定义了如下几个纯虚函数:

virtual spgetService( const String16& name)const = 0;

virtual spcheckService( const String16&name) const = 0;

virtual status_taddService( const String16&name,

const sp& service) = 0;

virtual VectorlistServices() = 0;

二、class

BnServiceManager : public BnInterface

展开就是classBnServiceManager :publicIServiceManager, public BBinder

即继承了IServiceManager和BBinder,他是ServiceManager的一个本地对象。

声明一个重要的虚汗数

virtual status_tonTransact(uint32_t code,

const Parcel& data,

Parcel*reply,

uint32_tflags = 0);

用来对消息进行分发。

三、class

BpServiceManager : public BpInterface

展开就class

BpServiceManager : public IServiceManager, public BpRefBase

即继承了IServiceManager和BpRefBase,他是ServiceManager的一个代理对象。

此代理对象对所有的消息进行处理

四、

这个文件中注意一个重要的全局函数,

sp

defaultServiceManager()

用来创建一个全局的IServiceManager对象,

sp

gDefaultServiceManager;

这个函数也创建的是单例,因为函数实现的第一句是,

if (gDefaultServiceManager != NULL) return

gDefaultServiceManager;

里面有这样一句话,

gDefaultServiceManager = interface_cast(

ProcessState::self()->getContextObject(NULL));

这样演变,

gDefaultServiceManager = interface_cast(newBpBinder(0));

gDefaultServiceManager = IServiceManager::asInterface(new BpBinder(0));

看下IServiceManager::asInterface的定义:

android::sp I##INTERFACE::asInterface(\

const android::sp& obj)\

{\

android::sp intr;\

if (obj != NULL) {\

intr =static_cast(\

obj->queryLocalInterface(\

I##INTERFACE::descriptor).get());\

if (intr == NULL) {\

intr = newBp##INTERFACE(obj);\

}\

}\

return intr;\

}\

android::sp IServiceManager::asInterface(constandroid::sp& obj)

{

android::sp intr;

if (obj != NULL) {

intr = static_cast(

obj->queryLocalInterface(IServiceManager::descriptor).get());

if (intr == NULL) {

intr = new BpServiceManager(obj);

}

}

return intr;

}

因为new BpBinder(0)不为空,所以执行

static_cast(

obj->queryLocalInterface(IServiceManager::descriptor).get());

执行(new

BpBinder(0))的queryLocalInterface方法,BpBinder没有重定义此虚函数,它继承自IBinder,IBinder已经实现,将调用基类IBinder的此函数,可以看到,

spIBinder::queryLocalInterface(constString16& descriptor)

{

return NULL;

}

返回NULL,因此它将执行

intr = new BpServiceManager(obj);

intr = new BpServiceManager(new

BpBinder(0));

因此函数defaultServiceManager,最终返回new BpServiceManager(new

BpBinder(0))给gDefaultServiceManager。

gDefaultServiceManager = new

BpServiceManager(new BpBinder(0));

五、

通过BpServiceManager的构造函数

BpServiceManager(const sp& impl)

: BpInterface(impl)

{

}

可以看到new

BpBinder(0)传给BpInterface(new

BpBinder(0)),在调用BpInterface的构造函数,

template

inline

BpInterface::BpInterface(const sp& remote)

:BpRefBase(remote)

{

}

继续传给基类BpRefBase的构造函数,

BpRefBase::BpRefBase(const

sp& o)

:mRemote(o.get()), mRefs(NULL), mState(0)

{

extendObjectLifetime(OBJECT_LIFETIME_WEAK);

if (mRemote) {

mRemote->incStrong(this);// Removed on first IncStrong().

mRefs = mRemote->createWeak(this);// Held for our entire lifetime.

}

}

所以

new BpBinder(0)

最终是保存在了BpRefBase中的

IBinder* constmRemote;

成员变量中。

7、

ProcessState.h

ProcessState.cpp

class ProcessState : public virtual

RefBase{}

此文件定义类对象

gProcess = new ProcessState

,他是一个单例模式,每个进程只会有一个,可以通过函数声明

staticspself();

它是static的确定。

ProcessState的主要作用:

(1)、打开/dev/binder,建立与内核Binder驱动交互的通道;

(2)、对返回的fd进行mmap映射,使内核Binder驱动分配一块内存接受数据,地址起始地址由成员变量mVMStart保存;

(3)、由于具有唯一性,只会创建一次,因此一个设备直打开设备/dev/binder一次,一旦打开,全局有效(因为使用全变变量gProcess保存的),后续直接使用即可。

8、

IPCThreadState.h

IPCThreadState.cpp

定义类class

IPCThreadState{}

此类用来创建一个线程在和Binder交互工作中使用的数据IPCThreadState对象。

每个线程都有一个IPCThreadState,每个IPCThreadState都有一个mIn,一个mOut,mIn用来接收来自Binder设备的数据,而mOut用来存储发往Binder设备数据的。

一、静态取自身函数和构造函数

IPCThreadState* IPCThreadState::self()

{

if (gHaveTLS) {

restart:

const pthread_key_t k = gTLS;

IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);

if (st) return st;

return new IPCThreadState;

}

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;

}

其中

static pthread_key_t gTLS = 0;

用来表示线程本地存储空间(Thread

Local Storage)的ID,如果它存在表示IPCThreadState(代表线程本地存储空间)已经创建,使用

IPCThreadState* st =

(IPCThreadState*)pthread_getspecific(k)将其取出,然后返回它的值。

如果为空,使用return

new IPCThreadState;创建一个。

如果gHaveTLS不存在,代表线程本地存储空间未建立,用

(pthread_key_create(&gTLS,

threadDestructor) != 0)

进行创建,然后跳到restart处,将其放回。

IPCThreadState::IPCThreadState()

:mProcess(ProcessState::self()),

mMyThreadId(androidGetTid()),

mStrictModePolicy(0),

mLastTransactionBinderFlags(0)

{

pthread_setspecific(gTLS,this);

clearCaller();

mIn.setDataCapacity(256);

mOut.setDataCapacity(256);

}

注意其中的函数调用

pthread_setspecific(gTLS, this);

将gTLS和对象IPCThreadState联系到一起。

另外,初始化列表中有mProcess(ProcessState::self()),说明使用mProcess将本进程进行了保存。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341

推荐阅读更多精彩内容