Android中怎么利用Binder機制實現(xiàn)進程間通信

這篇文章給大家介紹Android中怎么利用Binder機制實現(xiàn)進程間通信,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

創(chuàng)新互聯(lián)2013年開創(chuàng)至今,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目成都網(wǎng)站設(shè)計、成都網(wǎng)站建設(shè)、外貿(mào)網(wǎng)站建設(shè)網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元北安做網(wǎng)站,已為上家服務(wù),為北安各地企業(yè)和個人服務(wù),聯(lián)系電話:13518219792

第一步:獲取ManagerService服務(wù)代理BpBinder(0)和BpManagerService

第二步:通過BpManagerService中得addService方法將服務(wù)的一些信息打包,然后通過BpBinder(0)將信息發(fā)送到內(nèi)核,等待ManagerService進程來讀取,因為ManagerService進程中有一個Loop一直讀取內(nèi)核信息,所以很快就獲取了service發(fā)給內(nèi)核的信息,ManagerService進程就將service服務(wù)的一些信息添加到維護的列表中,將添加的結(jié)果發(fā)送給內(nèi)核,然后service等到內(nèi)核有回復(fù)后返回,將返回的信息解碼分析。

第三步:執(zhí)行一個Loop來從內(nèi)核讀取client的請求

代碼

如下是添加一個service的代碼

第一步:

sp<ProcessState> proc(ProcessState::self());

sp<IServiceManager> sm = defaultServiceManager();

第二步:

defaultServiceManager()->addService(String16("media.player"),new MediaPlayerService());

第三步:

ProcessState::self()->startThreadPool();

IPCThreadState::self()->joinThreadPool();

代碼分析

sp<ProcessState> proc(ProcessState::self());

創(chuàng)建一個ProcessState實例

ProcessState::mDriverFD=open_driver()

ProcessState::mVMstart = mmap(…,mDriverFD,…);

mmap(0,…,mDriverFD,0);//只是讓通信更快,可以當作沒有,直接用read/write(mDriverFD);

sp<IServiceManager> sm = defaultServiceManager();

主要執(zhí)行如下代碼

sp<IServiceManager> gDefaultServiceManager =interface_cast<IServiceManager>(PorcessState::self()->getContextObject(NULL));

其中PorcessState::self()->getContextObject(NULL)就是執(zhí)行PorcessState::getStrongProxyForHandle(0);其主要是根據(jù)給定的參數(shù)(此處為0)創(chuàng)建對應(yīng)的sp<IBinder>  b = new BpBinder(0);

這邊先說明interface_case這個模版類,這個模版類作用是將服務(wù)xxxService對應(yīng)的BpBinder(x)轉(zhuǎn)化為對應(yīng)的BpxxxService如下:

sp<IxxxService> BpxxxService= interface_cast<IxxxService>(newBpBinder(x));

其本質(zhì)是調(diào)用給定類型參數(shù)的asInterface方法,也就是IxxxService::asInterface(new BpBinder(x)),IxxxService繼承publicIInterface

IxxxService用宏DECLARE_META_INTERFACE(xxxService)和IMPLEMENT_META_INTERFACE(xxxService,”android.os.IxxxService”)來實現(xiàn)asInterface方法,展開后如 new BpxxxService(new BpBinder(x)),這樣就從BpBinder(x)得到了BpxxxService

如本例中給定的類型參數(shù)是IServiceManager,所以上述等價于

sp<IServiceManager> gDefaultServiceManager =IServiceManager::asInterface(new BpBinder(0)); IServiceManager繼承publicIInterface

其中用宏DECLARE_META_INTERFACE(ServiceManager) 和IMPLEMENT_META_INTERFACE(ServiceManager,”android.os.IServiceManager”)來實現(xiàn)asInterface方法,這個asInterface方法最終執(zhí)行new BpServiceManager(new BpBinder(0));

也就是sp<IServiceManager> sm = newBpServiceManager(new BpBinder(0));

由此得到BpBinder(0)和BpServiceManager

從這里可以得出,如果自己創(chuàng)建服務(wù)xxxService,按如下步驟

創(chuàng)建類 class IxxxService:publice IInterface

{
    DECLARE_META_INTERFACE(xxxService);//聲明asInterface方法

    virtual function();//虛函數(shù),由BpxxxService實現(xiàn)

    …

}

IMPLEMENT_META_INTERFACE(xxxService,”android.os.IxxxService”);//定義asInterface

展開相當于sp<IxxxService>IxxxService::asInterface(BpBinder){
    return new BpxxxService

}

當有這個服務(wù)的Bpbinder(x)后可通過如下獲取BpxxxService

sp<IxxxService>sm = new BpxxxService (new BpBinder(x));   

注意:

1:BpxxxService類型為sp<IxxxService>

2:BpBinder(x)相當于xxxService對應(yīng)binder實體的代理

3:客戶端為什么要通過BpBinder(X)再創(chuàng)建一個BpxxxService呢?因為BpxxxService對象的基類中的一個mRemote變量就是Bpbinder(x),那為什么不直接用BpBinder(x)呢?因為BpxxxService對象中還實現(xiàn)了一些BpBinder(x)沒有的業(yè)務(wù)邏輯(實現(xiàn)基類IxxxService中的方法)如BpServiceManager中提供了addService方法,這些方法在服務(wù)端有對應(yīng)的服務(wù),如addService方法將請求的命令”addService”和數(shù)據(jù)打包成Parcel類型,然后通過BpBinder(x)發(fā)送給xxxService,其實先發(fā)給驅(qū)動中binder設(shè)備,xxxService服務(wù)中會有Loop循環(huán)一直讀取binder設(shè)備的消息,讀取消息后解析成命令+數(shù)據(jù),然后根據(jù)命令如”addService”會調(diào)取對應(yīng)的服務(wù),然后將結(jié)果反饋給binder設(shè)備,客戶端接收到binder設(shè)備的反饋后將返回的數(shù)據(jù)也解析成命令+數(shù)據(jù),然后根據(jù)命令和數(shù)據(jù)執(zhí)行相應(yīng)的邏輯

客戶端 通過BpxxxService中方法將數(shù)據(jù)打包 -->Bpbinder(x)--> binder設(shè)備 --> 服務(wù)端Loop 獲取數(shù)據(jù)解析成命令+數(shù)據(jù)-->調(diào)取命令指定的服務(wù)其中會涉及BBinder和BnxxxService,返回數(shù)據(jù)

客戶端 解析返回的數(shù)據(jù)并執(zhí)行相應(yīng)邏輯     <--Bpbinder(x)<-- binder設(shè)備 <-- 服務(wù)端返回數(shù)據(jù)

由上可知,創(chuàng)建的服務(wù)還需創(chuàng)建BnxxxService和BpxxxService

class BpxxxService : public BpInterface<IxxxService>

{
    …

    vitural function(){
        Parcel data,reply;

        data.writeInterfaceToken(IxxxService::getInterfaceDescriptor());

        data.writeInt32(pid);

        remote()->transact(命令碼,data,&reply);

}

}

class BnxxxService: public BnInterface<IxxxService>

{
    public:

        vitrual status_t onTransact(uint32_tcode,const Parcel& data,Parcel* reply,uint32_t flags = 0);

}

IMPLEMENT_META_INTERFACE(xxxService,”android.xxxService.IxxxService”);

status_t BnxxxService::onTransact(uint32_tcode,const Parcel& data,Parcel* reply,uint32_t flags)

{
    switch(code){
        case 命令碼:

            CHECK_INTERFACE(IxxxService,data,reply);

            function()//自己實現(xiàn)的邏輯

break;

}

defaultServiceManager()->addService(String16("media.player"),new MediaPlayerService());

通過BpServiceManager(類型為sp<IServiceManager>)將數(shù)據(jù)打包成含”addService”命令,類型為parcel data的數(shù)據(jù),調(diào)用BpBinder(0)這個對象的transact(),最終調(diào)到IPCThreadState::self()->transact(),

下面分析IPCThreadState,你暫時只需要知道每個線程有一個IPCThreadState實例,實例有屬性mIn,mOut,其中mIn用來接受來自binder設(shè)備的parcel類型數(shù)據(jù),mOut用來存儲發(fā)往binder設(shè)備的parcel類型數(shù)據(jù),IPCThreadState::self()->transact()最終完成與binder設(shè)備的交互,這個接口中先調(diào)用writeTransactionData把parcel類型的數(shù)據(jù)和int32_t類型的命令碼封裝成binder_transaction_data類型數(shù)據(jù)放到IPCThreadState實例的mOut中去,接下來IPCThreadState::self()->transact()會調(diào)用IPCThreadState::self()->waitForResponse接口,其中會調(diào)用talkWithDriver()與binder設(shè)備交換數(shù)據(jù)(talkwithDriver主要是實現(xiàn)是ioctl(mProcess->mDriverFD,BINDER_WRITE_READ, &bwr)),將返回來的數(shù)據(jù)存于IPCThreadState實例的mIn,然后調(diào)用executeCommand()根據(jù)mIn中得命令碼和數(shù)據(jù)來解析,來調(diào)用各種業(yè)務(wù)邏輯

ServiceManager這個服務(wù)的Loop循環(huán)實現(xiàn)代碼見下面:

struct binder_state *bs;

void *svcmgr = BINDER_SERVICE_MANAGER;

bs = binder_open(128*1024);//應(yīng)該是打開binder設(shè)備吧

binder_become_context_manager(bs) //成為manager

svcmgr_handle = svcmgr;

binder_loop(bs, svcmgr_handler);//Loop

new MediaPlayerService(),MediaPlayerService繼承BnMediaPlayService,BnMediaPlayService繼承BnInterface, BnInterface繼承BBinder ,BBinder繼承 IBinder,所以MediaPlayerService繼承了IBinder,addService第二個參數(shù)類型是IBinder 實例一個MediaPlayService也就是實例一個BnMediaPlaySerivce

ProcessState::self()->startThreadPool();

IPCThreadState::self()->joinThreadPool();

創(chuàng)建一個MediaPlayerService服務(wù)后(也就是創(chuàng)建一個BnMediaPlaySerivce)后,將其加入serviceManage維護的一個列表中,接下來,BnMediaPlaySerivce也該起到服務(wù)的作用,創(chuàng)建一個Loop等待客戶端client的請求,所以應(yīng)該也有一個循環(huán),也就是如下兩段代碼的作用

ProcessState::self()->startThreadPool();

IPCThreadState::self()->joinThreadPool();

先分析ProcessState::self()->startThreadPool();

其調(diào)用

sp<Thread> t = new PoolThread(isMain);isMain是TRUE

t->run(buf);//這句話會導致t->threadLoop調(diào)用,這里面執(zhí)行了IPCThreadState::self()->joinThreadPool(mIsMain);

所以歸根結(jié)底最后都調(diào)用IPCThreadState::self()->joinThreadPool(mIsMain);

這里面主要是執(zhí)行一個循環(huán),

    do {
        int32_tcmd;

        result =talkWithDriver();

        result =executeCommand(cmd);

     }

} while (result != -ECONNREFUSED && result !=-EBADF);

總結(jié):調(diào)用talkWithDriver()與binder設(shè)備交換數(shù)據(jù)(talkwithDriver主要是實現(xiàn)是ioctl(mProcess->mDriverFD,BINDER_WRITE_READ, &bwr)),將返回來的數(shù)據(jù)存于IPCThreadState實例的mIn,然后調(diào)用executeCommand()根據(jù)mIn中得命令碼和數(shù)據(jù)來解析,來調(diào)用自己(此處是BnMediaPlaySerivce)的各種業(yè)務(wù)邏輯,例如如果受到的命令是BR_TRANSACTION則會調(diào)用reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code,buffer, &reply, tr.flags);結(jié)果調(diào)用BnMediaPlaySerivce的oNTransact方法

這里面會根據(jù)獲取的mIn中得命令碼和數(shù)據(jù)來調(diào)用不同的業(yè)務(wù)邏輯,然后派發(fā)到派生類MediaService(自己創(chuàng)建的)的函數(shù),由他們完成實際的工作

常用有如下情形2:client訪問某個服務(wù)service

過程

第一步:獲取ManagerService服務(wù)代理BpBinder(0)和BpManagerService

第二步:通過BpManagerService中得getService方法將服務(wù)的一些信息打包,然后通過BpBinder(0)將信息發(fā)送到內(nèi)核,等待ManagerService進程來讀取,因為ManagerService進程中有一個Loop一直讀取內(nèi)核信息,所以很快就獲取了client發(fā)給內(nèi)核的信息,ManagerService進程將client想知道的東西發(fā)送給內(nèi)核,client等到內(nèi)核有回復(fù)后返回,將返回的信息解碼分析已得知有無某個service服務(wù),如果有這個service則返回的信息中有這個service的Bpbinder(x),client可以通過sp<Iservice>Bpservice = interface_cast<Iservice>( Bpbinder(x));來獲取BpService,BpService中有與service對應(yīng)的服務(wù)

第三步:訪問服務(wù)

client訪問這些服務(wù)前先調(diào)BpService中對應(yīng)特定服務(wù)其將數(shù)據(jù)及命令打包,通過Bpbinder(x)將信息發(fā)送到內(nèi)核,應(yīng)為service也有一個Loop一直在讀取內(nèi)核信息,所以service很快就獲取了client發(fā)來的信息,解析后根據(jù)信息中得命令碼將數(shù)據(jù)發(fā)送到Bnservice對象包含的方法中進行解析,然后將處理后的數(shù)據(jù)發(fā)送給內(nèi)核,client等到內(nèi)核的受到的消息后返回,將返回的消息解碼然后處理

代碼

如下是client獲取service的的代碼

第一步:

sp<ProcessState> proc(ProcessState::self());

sp<IServiceManager> sm=defaultServiceManager();

見上

第二步:

sp<IBinder> binder = sm->getServices(String16(“media.player”));

sp<IMediaPlayService> sMediaPlayService =interface_cast<IMediaPlayService>(binder);

關(guān)于Android中怎么利用Binder機制實現(xiàn)進程間通信就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

當前標題:Android中怎么利用Binder機制實現(xiàn)進程間通信
網(wǎng)頁網(wǎng)址:http://bm7419.com/article12/ijhsgc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應(yīng)網(wǎng)站動態(tài)網(wǎng)站、網(wǎng)站排名、網(wǎng)站導航移動網(wǎng)站建設(shè)、建站公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都app開發(fā)公司