Android binder機(jī)制(native服務(wù)篇)

** 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)于網(wǎng)絡(luò)。

Paste_Image.png

本文以MediaPlayerService為例,闡述binder機(jī)制。

2、ServiceManager

ServiceManager,顧名思義,服務(wù)的管理者,所有的本地服務(wù)在啟動的時(shí)候都會被保存在ServiceManager中,而用戶可直接訪問ServiceManager,獲取所需要的服務(wù)。

ServiceManager運(yùn)行在一個(gè)獨(dú)立進(jìn)程中,本地服務(wù)在啟動時(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ā)出請求,存儲服務(wù),ServiceManager此時(shí)做為Server端,那么defaultServiceManager究竟返回的是什么對象呢?

3、痛苦的宏定義
繼續(xù)查看ProcessState::self()->getContextObject(NULL)邏輯,ProcessState使用單例模式,確保一個(gè)進(jìn)程中只有一個(gè)ProcessState對象。

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ū)動
, 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ū)動,整篇都在講binder,終于提到有個(gè)類與binder驅(qū)動交互了。

繼續(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;
    //第一次查找,顯示會得到空值
    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文件中是否會有另外一定宏定義,來實(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文件,會發(fā)現(xiàn)這段代碼和aidl被編譯器自動處理過后的文件非常相似,如果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ū)動正式通信

查看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ū)動通信。問題來了,那remote()方法得到的是什么對象呢?

remote()方法返回的是mRemote對象,回溯上文所講的asInterface方法,構(gòu)造BpServiceManager對象,傳入了一個(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方法。

Paste_Image.png

根據(jù)在java中使用aidl的經(jīng)驗(yàn),調(diào)用transact方法后,最終肯定會調(diào)用到onTransact,最終調(diào)用到Server端的方法。

BpBinder的transact之后的調(diào)用流程如上,尤其關(guān)注IPCThreadState類。根據(jù)上圖,IPCThreadState與Binder驅(qū)動通信,分別調(diào)用三個(gè)方法

  • writeTransactionData,向Binder驅(qū)動寫數(shù)據(jù)
  • waitForResponse, 等待Binder驅(qū)動返回指令
  • executeCommand,執(zhí)行Binder驅(qū)動的指令

目前和Binder驅(qū)動相關(guān)的代碼已經(jīng)有兩個(gè)類了,一個(gè)是ProcessState,另一個(gè)是IPCThreadState,他們的關(guān)系如何,待會再說。

已經(jīng)調(diào)用了onTransact方法,按理說,應(yīng)該要調(diào)用Server端的方法了,可ServiceManager的server端代碼在哪里呢?

ServiceManager是一個(gè)特殊的服務(wù),因?yàn)樗欠?wù)的管理者,它在其它服務(wù)啟動之前啟動,它的server端代碼在Service_manager.c類中,查看它的main方法。

int main(int argc, char **argv)
{
struct binder_state *bs;
//打開Binder驅(qū)動
bs = binder_open(128*1024);
//將自己設(shè)定為服務(wù)的管理者,管理者對象,整個(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)了什么操作呢?

Paste_Image.png

到目前為止,針對ServiceManager,從client端發(fā)起請求,到服務(wù)端響應(yīng)請求的整個(gè)流程已經(jīng)講完了。

5、MediaPlayerService

根據(jù)ServiceManager的分析經(jīng)驗(yàn),一個(gè)本地服務(wù)至少涉及到以下幾個(gè)類

  • I××Service.h,定義接口,引用宏定義等,從后文可知,它還會定義BN××Service類
  • I××Service.cpp,定義Bp××Service類,聲明實(shí)現(xiàn)宏定義,從后文可知,它還會重寫B(tài)N××Service類的onTransact方法
  • Service_manager.c,類似的看似不相關(guān)文件,打開binder驅(qū)動,初始化,循環(huán)讀取binder驅(qū)動消息等
  • ××Service.cpp,I××Service.h中接口的具體實(shí)現(xiàn)者,ServiceManager中server端的具體邏輯實(shí)現(xiàn)在Service_manager.c中,但一般來說,會有這樣的一個(gè)類,實(shí)現(xiàn)具體邏輯

MediaPlayerService服務(wù)的初始化在Main_mediaserver.cpp中,對應(yīng)著ServiceManager系統(tǒng)的Service_manager.c,負(fù)責(zé)初始化,打開binder驅(qū)動,建議消息循環(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();
}

然道先前的推測不對?main方法中并沒有直接打開binder,也沒有建立消息循環(huán)。聯(lián)想到前文中的內(nèi)容,與Binder驅(qū)動打交道的主要有兩個(gè)類,一是ProcessState,另一個(gè)就是IPCThreadState。

在ProcessState的構(gòu)造方法中,已經(jīng)打開了binder驅(qū)動。

從代碼上看 ProcessState::self()->startThreadPool(),好像是啟動線程。


Paste_Image.png

查看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ū)動中取出指令并執(zhí)行
        result = getAndExecuteCommand();
    } while (result != -ECONNREFUSED && result != -EBADF);
    
    mOut.writeInt32(BC_EXIT_LOOPER);
    talkWithDriver(false);
}

此方法正好是建立消息死循環(huán),與binder驅(qū)動溝通,取指令,執(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,線程局部存儲,變量與線程相關(guān),每個(gè)線程私有,不必考慮加鎖問題,類似于java中的ThreadLocal類

由此可見,IPCThreadState,它是每個(gè)線程所獨(dú)有的對象。
ProcessState是進(jìn)程唯一的對象,這是兩個(gè)非常有意思的單例。

這兩個(gè)類都有與Binder驅(qū)動通信的邏輯,實(shí)質(zhì)上是,IPCThreadState的構(gòu)造方法中傳入了ProcessState對象,IPCThreadState利用ProcessState與binder驅(qū)動通信

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容