** 1、前言 **
Android系統(tǒng)使用binder機(jī)制進(jìn)行進(jìn)程間通信,為了更好地封裝,使用戶不用關(guān)心底層細(xì)節(jié),binder機(jī)制變得相當(dāng)復(fù)雜。
binder使用c/s架構(gòu),可類比socket通信,有服務(wù)端也有客戶端 ,而binder驅(qū)動(dòng)就相當(dāng)于網(wǎng)絡(luò)。
本文以MediaPlayerService為例,闡述binder機(jī)制。
2、ServiceManager
ServiceManager,顧名思義,服務(wù)的管理者,所有的本地服務(wù)在啟動(dòng)的時(shí)候都會(huì)被保存在ServiceManager中,而用戶可直接訪問ServiceManager,獲取所需要的服務(wù)。
ServiceManager運(yùn)行在一個(gè)獨(dú)立進(jìn)程中,本地服務(wù)在啟動(dòng)時(shí)需要獲取ServiceManager,將自身保存,這也是一個(gè)IPC過程。此時(shí),ServiceManager作為服務(wù)端,而本地服務(wù)作為客戶端。
以MediaPlayerService為例,查看MediaPlayerService是如何與ServiceManager通信,并將自身保存的呢?
查看MediaPlayerService.cpp的instantiate方法:
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
}
查看defaultServiceManager源碼:
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
if (gDefaultServiceManager == NULL)
sleep(1);
}
}
return gDefaultServiceManager;
}
現(xiàn)在MediaPlayerService向ServiceManager發(fā)出請(qǐng)求,存儲(chǔ)服務(wù),ServiceManager此時(shí)做為Server端,那么defaultServiceManager究竟返回的是什么對(duì)象呢?
3、痛苦的宏定義
繼續(xù)查看ProcessState::self()->getContextObject(NULL)邏輯,ProcessState使用單例模式,確保一個(gè)進(jìn)程中只有一個(gè)ProcessState對(duì)象。
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
gProcess = new ProcessState;
return gProcess;
}
ProcessState的構(gòu)造方法中又做了什么呢?
ProcessState::ProcessState()
: mDriverFD(open_driver()) //初始化列表模式,打開binder驅(qū)動(dòng)
, mVMStart(MAP_FAILED)
。。。
{
if (mDriverFD >= 0) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
}
ProcessState構(gòu)造方法中,打開binder驅(qū)動(dòng),整篇都在講binder,終于提到有個(gè)類與binder驅(qū)動(dòng)交互了。
繼續(xù)查看getContextObject方法。
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
// 根據(jù) handle值,在Vector 中查找
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
IBinder* b = e->binder;
//第一次查找,顯示會(huì)得到空值
if (b == NULL || !e->refs->attemptIncWeak(this)) {
。。。
// 構(gòu)造一個(gè)BpBinder,最終返回它
b = new BpBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
}
。。。
}
return result;
}
回到前文的defaultServiceManager方法中,將返回值代入,得到
//注意,方法中傳入的handle為0,所以BpBinder參數(shù)為0
gDefaultServiceManager = interface_cast<IServiceManager>(new BpBinder(0));
interface_cast,初看以為是強(qiáng)制類型轉(zhuǎn)換的方法,以為自己太菜,這方法怎么沒見過一樣,左鍵點(diǎn)擊下查看方法,才發(fā)現(xiàn)別有洞天。
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
原來是調(diào)用泛型類中的asInterface的方法,那么IServiceManager的asInterface的具體邏輯是什么呢?查看IServiceManager.h或者cpp文件查看,都找不到asInterface這個(gè)方法。但看到了下面一段聲明:
// IServiceManager.h 中引用的
DECLARE_META_INTERFACE(ServiceManager);
點(diǎn)擊一看,這個(gè)宏定義中正好定義了asInterface 方法。
#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(); \
但這只是方法定義,哪里實(shí)現(xiàn)的呢?已經(jīng)在h文件中看到宏定義了,那么cpp文件中是否會(huì)有另外一定宏定義,來實(shí)現(xiàn)此方法呢? 答案是肯定的,在IServiceManager.cpp中果然看到一段宏定義
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
點(diǎn)擊查看宏定義具體內(nèi)容:
#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() { } \
將模板替換,可知asInterface方法代碼為:
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; \
}
如果有看過java中的aidl文件,會(huì)發(fā)現(xiàn)這段代碼和aidl被編譯器自動(dòng)處理過后的文件非常相似,如果client端和server端不在同一進(jìn)程,那么必定走的流程是返回 BpServiceManager 。
BpServiceManager 類在哪呢?它定義在IServiceManager.cpp文件中。
一般native服務(wù)的接口定義在 I××Service.h 文件中,Bp××Service一般定義在I××Service.cpp文件當(dāng)中
經(jīng)過一系列的折騰,終于回到MediaPlayerService.cpp的instantiate方法了,代替下就是
void MediaPlayerService::instantiate() {
BpServiceManager->addService(String16("media.player"), new MediaPlayerService());
}
4、和Binder驅(qū)動(dòng)正式通信
查看BpServiceManager的addService方法
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated)
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
感覺這段代碼非常眼熟,和java中的aidl差別不大,主要就是調(diào)用remote()->transact,和Binder驅(qū)動(dòng)通信。問題來了,那remote()方法得到的是什么對(duì)象呢?
remote()方法返回的是mRemote對(duì)象,回溯上文所講的asInterface方法,構(gòu)造BpServiceManager對(duì)象,傳入了一個(gè)BpBinder,查看BpServiceManager的構(gòu)造函數(shù),它最終引用父類BpRefBase的構(gòu)造函數(shù)。
BpRefBase::BpRefBase(const sp<IBinder>& o)
: mRemote(o.get()), mRefs(NULL), mState(0)
{
。。。。
}
于是得知addService方法中,其實(shí)是調(diào)用BpBinder的transact方法。
根據(jù)在java中使用aidl的經(jīng)驗(yàn),調(diào)用transact方法后,最終肯定會(huì)調(diào)用到onTransact,最終調(diào)用到Server端的方法。
BpBinder的transact之后的調(diào)用流程如上,尤其關(guān)注IPCThreadState類。根據(jù)上圖,IPCThreadState與Binder驅(qū)動(dòng)通信,分別調(diào)用三個(gè)方法
- writeTransactionData,向Binder驅(qū)動(dòng)寫數(shù)據(jù)
- waitForResponse, 等待Binder驅(qū)動(dòng)返回指令
- executeCommand,執(zhí)行Binder驅(qū)動(dòng)的指令
目前和Binder驅(qū)動(dòng)相關(guān)的代碼已經(jīng)有兩個(gè)類了,一個(gè)是ProcessState,另一個(gè)是IPCThreadState,他們的關(guān)系如何,待會(huì)再說。
已經(jīng)調(diào)用了onTransact方法,按理說,應(yīng)該要調(diào)用Server端的方法了,可ServiceManager的server端代碼在哪里呢?
ServiceManager是一個(gè)特殊的服務(wù),因?yàn)樗欠?wù)的管理者,它在其它服務(wù)啟動(dòng)之前啟動(dòng),它的server端代碼在Service_manager.c類中,查看它的main方法。
int main(int argc, char **argv)
{
struct binder_state *bs;
//打開Binder驅(qū)動(dòng)
bs = binder_open(128*1024);
//將自己設(shè)定為服務(wù)的管理者,管理者對(duì)象,整個(gè)android系統(tǒng)只有一個(gè)
if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
//開啟循環(huán),從binder中讀取命令,執(zhí)行命令
binder_loop(bs, svcmgr_handler);
}
再次回到onTransact方法,現(xiàn)在server端代碼找到了,client端調(diào)用了addService,那么server端響應(yīng)了什么操作呢?
到目前為止,針對(duì)ServiceManager,從client端發(fā)起請(qǐng)求,到服務(wù)端響應(yīng)請(qǐng)求的整個(gè)流程已經(jīng)講完了。
5、MediaPlayerService
根據(jù)ServiceManager的分析經(jīng)驗(yàn),一個(gè)本地服務(wù)至少涉及到以下幾個(gè)類
- I××Service.h,定義接口,引用宏定義等,從后文可知,它還會(huì)定義BN××Service類
- I××Service.cpp,定義Bp××Service類,聲明實(shí)現(xiàn)宏定義,從后文可知,它還會(huì)重寫B(tài)N××Service類的onTransact方法
- Service_manager.c,類似的看似不相關(guān)文件,打開binder驅(qū)動(dòng),初始化,循環(huán)讀取binder驅(qū)動(dòng)消息等
- ××Service.cpp,I××Service.h中接口的具體實(shí)現(xiàn)者,ServiceManager中server端的具體邏輯實(shí)現(xiàn)在Service_manager.c中,但一般來說,會(huì)有這樣的一個(gè)類,實(shí)現(xiàn)具體邏輯
MediaPlayerService服務(wù)的初始化在Main_mediaserver.cpp中,對(duì)應(yīng)著ServiceManager系統(tǒng)的Service_manager.c,負(fù)責(zé)初始化,打開binder驅(qū)動(dòng),建議消息循環(huán)等等
int main(int argc __unused, char** argv)
{
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
MediaPlayerService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
然道先前的推測(cè)不對(duì)?main方法中并沒有直接打開binder,也沒有建立消息循環(huán)。聯(lián)想到前文中的內(nèi)容,與Binder驅(qū)動(dòng)打交道的主要有兩個(gè)類,一是ProcessState,另一個(gè)就是IPCThreadState。
在ProcessState的構(gòu)造方法中,已經(jīng)打開了binder驅(qū)動(dòng)。
從代碼上看 ProcessState::self()->startThreadPool(),好像是啟動(dòng)線程。
查看IPCThreadState的joinThreadPool方法
void IPCThreadState::joinThreadPool(bool isMain)
{
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
set_sched_policy(mMyThreadId, SP_FOREGROUND);
status_t result;
do {
processPendingDerefs();
// 從binder驅(qū)動(dòng)中取出指令并執(zhí)行
result = getAndExecuteCommand();
} while (result != -ECONNREFUSED && result != -EBADF);
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
此方法正好是建立消息死循環(huán),與binder驅(qū)動(dòng)溝通,取指令,執(zhí)行指令等等。
但為什么此方法被調(diào)用兩次呢?ProcessState的startThreadPool方法調(diào)用一次,而main方法最后又調(diào)用了一次,在工作線程中調(diào)用了,在主線程也調(diào)用了。是否可去掉其中之一,筆者不得而知。
IPCThreadState::self(),此方法又做了哪些工作呢?
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;
}
pthread_mutex_lock(&gTLSMutex);
if (!gHaveTLS) {
int key_create_value = pthread_key_create(&gTLS, threadDestructor);
if (key_create_value != 0) {
pthread_mutex_unlock(&gTLSMutex);
return NULL;
}
gHaveTLS = true;
}
pthread_mutex_unlock(&gTLSMutex);
goto restart;
}
TLS,線程局部存儲(chǔ),變量與線程相關(guān),每個(gè)線程私有,不必考慮加鎖問題,類似于java中的ThreadLocal類
由此可見,IPCThreadState,它是每個(gè)線程所獨(dú)有的對(duì)象。
ProcessState是進(jìn)程唯一的對(duì)象,這是兩個(gè)非常有意思的單例。
這兩個(gè)類都有與Binder驅(qū)動(dòng)通信的邏輯,實(shí)質(zhì)上是,IPCThreadState的構(gòu)造方法中傳入了ProcessState對(duì)象,IPCThreadState利用ProcessState與binder驅(qū)動(dòng)通信
6、MediaPlayerService相關(guān)文件
IMediaPlayerService.h中定義了server端應(yīng)該實(shí)現(xiàn)的接口,也定義了BnMediaPlayerService類
和前文中的IServiceManager.h一樣
IMediaPlayerService.cpp中定義了BpMediaPlayerService類,也重寫了BnMediaPlayerService的onTransact方法
IMediaPlayerService.h中定義的方法,在MediaPlayerService.cpp中具體實(shí)現(xiàn)。
7、總結(jié)
MediaPlayerService的client端與server端通信,和ServiceManager模塊中類似,就不再復(fù)述。
此時(shí)再結(jié)合前言中的圖片,如果每個(gè)類都做到心中有數(shù)了,那native服務(wù)的binder機(jī)制就基本了解了。
引用材料:
http://www.cnblogs.com/innost/archive/2011/01/09/1931456.html
http://blog.csdn.net/victorfreedom/article/details/43648309
http://blog.csdn.net/ykdsea/article/details/39271133