Android Binder機制淺析(一)

Android Binder機制淺析(一),Binder是Android系統進程間通信(IPC)方式之一。Linux已經擁有的進程間通信IPC手段包括(Internet Process Connection): 管道(Pipe)、信號(Signal)和跟蹤(Trace)、插口(Socket)、報文隊列(Message)、共享內存(Share Memory)和信號量(Semaphore)。本文分析的是Binder的實現以及Binder組件Client、Server和Service Manager、Binder驅動的相互關系

本文根據網上現有資源進行整合,以及自己的理解,有誤之處歡迎指正~~

一、概述

Android系統 Binder機制中有四個組件Client、Service、ServiceManager和Binder驅動程序,大致模型如下

  1.Client、Server和ServiceManager實現在用戶空間中,Binder驅動程序實現在內核空間中

  2.Binder驅動程序和ServiceManager在Android平臺中已經實現,開發者隻需要在用戶空間實現自己的Client和Server

3.Binder驅動程序提供設備文件/dev/binder與用戶空間交互,Client、Server和ServiceManager通過open和ioctl文件操作函數與Binder驅動程序進行通信

4.Client和Server之間的進程間通信通過Binder驅動程序間接實現

5.ServiceManager是一個守護進程,用來管理Server,並向Client提供查詢Server接口的能力

 

本文以MediaServer為例,學習Binderd機制

ServiceManager:Android整個服務的管理程序

MediaService:    在此程序裡註冊提供媒體播放的服務程序MediaPlayerService

MediaPlayerClient與MediaPlayerService交互的客戶端程序

二、MediaService

源碼目錄在frameworks/av/media/mediaserver/main_mediaserver.cpp

Main()

signal(SIGPIPE,SIG_IGN);

>>spproc(ProcessState::self());

>>spsm(defaultServiceManager());ALOGI("ServiceManager:%p",sm.get());

InitializeIcuOrDie();

>>MediaPlayerService::instantiate();//初始化MediaService服務

……

ProcessState::self()->startThreadPool();//啟動線程池IPCThreadState::self()->joinThreadPool();

 

2.1ProcessState 類

調用ProcessState::self() ,然後賦值給proc變量,程序運行結束後,proc會自動delete內部內容,會自動釋放先前分配的資源

目錄在 frameworks/native/libs/binder/ProcessState.cpp

spProcessState::self()

{

Mutex::Autolock_l(gProcessMutex);

if(gProcess!=NULL){

returngProcess;

}

>>gProcess=newProcessState;

returngProcess;

//將由2.2中 gDefaultManagergetContextObject函數傳遞

}

追到ProcessState構造函數

ProcessState::ProcessState()

>>:mDriverFD(open_driver())

>>,mVMStart(MAP_FAILED)//映射內存起始地址

,mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)

,mThreadCountDecrement(PTHREAD_COND_INITIALIZER)

{

if(mDriverFD>=0){

//mmapthebinder,providingachunkofvirtualaddressspacetoreceivetransactions.

mVMStart=mmap(0,BINDER_VM_SIZE,PROT_READ,MAP_PRIVATE|MAP_NORESERVE,mDriverFD,0);

//將fd映射為內存,這樣內存的mmcpy等操作就相當於write/read瞭

if(mVMStart==MAP_FAILED){

//*sigh*

ALOGE("Using/dev/binderfailed:unabletommaptransactionmemory.\n");

close(mDriverFD);

mDriverFD=-1;

}

}

open_driver(),打開/dev/binder設備,是Android在內核中設置的一個用於完成進程間通信的虛擬設備,追代碼

staticintopen_driver()

{

intfd=open("/dev/binder",O_RDWR|O_CLOEXEC);

if(fd>=0){

intvers=0;

status_tresult=ioctl(fd,BINDER_VERSION,&vers);

size_tmaxThreads=DEFAULT_MAX_BINDER_THREADS;//最大支持線程數15個

result=ioctl(fd,BINDER_SET_MAX_THREADS,&maxThreads);

returnfd;

}

小結:ProcessState::self()作用

1. 打開/dev/binder設備,相當於和內核binder機制有瞭交互通道

2. 將fd映射到內存,設備fd傳入後,內存將於binder設備共享

接著分析defaultServiceManager

 

2.2defaultServiceManager

源碼目錄在 frameworks/native/libs/binder/IServiceManager.cpp

spdefaultServiceManager()

{

if(gDefaultServiceManager!=NULL)returngDefaultServiceManager;

  // 單例設計模式

{

AutoMutex_l(gDefaultServiceManagerLock);

while(gDefaultServiceManager==NULL){

//創建gDefaultServiceManager

>>gDefaultServiceManager=interface_cast(

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

}

}

returngDefaultServiceManager;

}

其中,ProcessState::self()返回的是剛才創建的gProcess,然後調用getContextObject(),傳參為NULL,即0

追getContextObject代碼

目錄在 frameworks/native/libs/binder/ProcessState.cpp

spProcessState::getContextObject(constsp&/*caller*/)

{

returngetStrongProxyForHandle(0);

}

追getStrongProxyForHandle

//handle是windows一種資源的標示 比如某個數據結構,保存在數組中,handle是它在數組中的索引

spProcessState::getStrongProxyForHandle(int32_thandle)

{

spresult;

AutoMutex_l(mLock);

handle_entry*e=lookupHandleLocked(handle);//從數組中查找對應索引的資源

….

b=newBpBinder(handle);

e->binder=b;

if(b)e->refs=b->getWeakRefs();

result=b;//返回創建的BpBinder

}

我們從

gDefaultServiceManager=interface_cast(

ProcessState::self()->getContextObject(NULL));追代碼

現在函數調用為 

gDefaultServiceManager=interface_cast(newBpBinder(0))

2.3BpBinder

目錄 frameworks/native/libs/binder/BpBinder.cpp

BpBinder::BpBinder(int32_thandle)

:mHandle(handle)//從上述傳遞為0

,mAlive(1)

,mObitsSent(0)

,mObituaries(NULL)

{

IPCThreadState::self()->incWeakHandle(handle);

}

在此,先追一下IPCThreadState()

目錄在 frameworks/native/libs/binder/IPCThreadState.cpp

IPCThreadState*IPCThreadState::self()

{

if(gHaveTLS){//第一次進為false

restart:

constpthread_key_tk=gTLS;

//TLS是ThreadLocalStorage線程本地存儲空間,每個線程都會有,但線程間不  會共享這些空間,可以不用再設置同步

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

//pthread_getspecific 獲取保存在TLS中的IPCThreadState對象

//在其他地方有調用

if(st)returnst;

returnnewIPCThreadState;

}

pthread_mutex_lock(&gTLSMutex);

gHaveTLS=true;

}

pthread_mutex_unlock(&gTLSMutex);

gotorestart;

}

追查pthread_getspecific函數,可得在

IPCThreadState構造函數裡有個pthread_setspecific

IPCThreadState::IPCThreadState()

:mProcess(ProcessState::self()),

mMyThreadId(gettid()),

mStrictModePolicy(0),

mLastTransactionBinderFlags(0)

{

pthread_setspecific(gTLS,this);

clearCaller();

//min、mout是兩個Parcel,讀取數據的容器

mIn.setDataCapacity(256);

mOut.setDataCapacity(256);

}

至此,再調用incWeakHandle(),handle為0

小結:

gDefaultServiceManager創建瞭

ProcessState、IPCThreadState(主線程中)、BpBinder(內部handle為0)

再次回到2.2最後的函數

>>gDefaultServiceManager=interface_cast(newBpBinder(0))

BpBinder分析之後,發現BpBinder*指針如何轉換為IServiceManager*,

由此關註interface_cast

回到2.2中的frameworks/native/libs/binder/IServiceManager.cpp

點擊interface_cast,跳轉至

frameworks/native/include/binder/IInterface.h

發現

inlinespinterface_cast(constsp&obj)

{

returnINTERFACE::asInterface(obj);

} 即,等價於

inlinespinterface_cast(constsp&obj)

{

returnIServiceManager::asInterface(obj);

}

於是,再次追IServiceManager,如何實現

2.4IServiceManager

目錄在 frameworks/native/include/binder/IServiceManager.h

//Service管理類,管理增加服務、查詢服務等

classIServiceManager:publicIInterface

{

public:

DECLARE_META_INTERFACE(ServiceManager);//類似MFC

virtualspgetService(constString16&name)const=0;

virtualspcheckService(constString16&name)const=0;

virtualstatus_taddService(constString16&name,

constsp&service,

boolallowIsolated=false)=0;

回到frameworks/native/include/binder/IInterface.h

DECLARE_META_INTERFACE

#defineDECLARE_META_INTERFACE(INTERFACE)\

>>staticconstandroid::String16descriptor;\

staticandroid::spasInterface(\

constandroid::sp&obj);\

>>virtualconstandroid::String16&getInterfaceDescriptor()const;\

//增加get函數,返回值即為descriptor字符串

I##INTERFACE();\

virtual~I##INTERFACE();\

IMPLEMENT_META_INTERFACE

#defineIMPLEMENT_META_INTERFACE(INTERFACE,NAME)\

constandroid::String16I##INTERFACE::descriptor(NAME);\

constandroid::String16&\

I##INTERFACE::getInterfaceDescriptor()const{\

>>returnI##INTERFACE::descriptor;

//返回上面android.os.IServerManager\

}\

>>android::spI##INTERFACE::asInterface(\

constandroid::sp&obj)\

{\

android::spintr;\

if(obj!=NULL){\

intr=static_cast(\

obj->queryLocalInterface(\

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

if(intr==NULL){\

intr=newBp##INTERFACE(obj);\

}\

}\

returnintr;\

}\

I##INTERFACE::I##INTERFACE(){}\

I##INTERFACE::~I##INTERFACE(){}

兩個宏分別兌現之後

NAME等價於android.os.IServerManager

##INTERFACE等價於IServiceManager

上面提到的 interface_cast(newBpBinder(0))就是調用

asInterface(newBpBinder(0))

android::spIServiceManager::asInterface(\

constandroid::sp&obj)\

{\

>>android::spintr;\

if(obj!=NULL){\

intr=static_cast(\

obj->queryLocalInterface(\

IServiceManager::descriptor).get());\

if(intr==NULL){\

>>intr=newBpServiceManager(obj);\

}\

}\

returnintr;\

}

在這裡,返回的intr=BpServiceManager(newBpBinder(0));

 

2.5BpServiceManager

目錄在 frameworks/native/libs/binder/IServiceManager.cpp

Bp 是Binderproxy,BpServiceManager是ServiceManager的Binder代理,

classBpServiceManager:publicBpInterface

{

>>// 這種繼承方式,標示同時繼承BpInterface和IServiceManager,故IServiceManager的addService在這個類中實現

public:

//impl?好像是Bridge模式,impl對象??

// 傳參的impl就是之前的newBpBinder(0)

  BpServiceManager(constsp&impl)

:BpInterface(impl)

{

}

virtualstatus_taddService(constString16&name,constsp&service,

boolallowIsolated)

{

}

這裡先追BpInterface,將INTERFACE兌現為IServiceManager

inlineBpInterface::BpInterface(constsp&remote)

:BpRefBase(remote)

//remote傳參

{

}

BpRefBase::BpRefBase(constsp&o)

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

//o.get()是sp類的獲取實際數據指針的一個方法,

// 它返回的是sp中的xxx*指針

//mRemote是剛才傳入的BpBinder(0)

{

}

}

至此,重新回到在第二章開始處 MediaServer的main中的

spsm(defaultServiceManager());

返回的實際是BpServiceManager它的remote對象是BpBinder,傳入的handle參數是0

同時,binder設備已經打開,得到一個BpServiceManager對象,

表示可以和ServiceManager打交道。

 

You May Also Like