真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

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

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

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

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

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

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

代碼

如下是添加一個(gè)service的代碼

第一步:

sp proc(ProcessState::self());

sp sm = defaultServiceManager();

第二步:

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

第三步:

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

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

代碼分析

sp proc(ProcessState::self());

創(chuàng)建一個(gè)ProcessState實(shí)例

ProcessState::mDriverFD=open_driver()

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

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

sp sm = defaultServiceManager();

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

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

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

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

sp BpxxxService= interface_cast(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”)來(lái)實(shí)現(xiàn)asInterface方法,展開(kāi)后如 new BpxxxService(new BpBinder(x)),這樣就從BpBinder(x)得到了BpxxxService

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

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

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

也就是sp 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實(shí)現(xiàn)

    …

}

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

展開(kāi)相當(dāng)于spIxxxService::asInterface(BpBinder){
    return new BpxxxService

}

當(dāng)有這個(gè)服務(wù)的Bpbinder(x)后可通過(guò)如下獲取BpxxxService

spsm = new BpxxxService (new BpBinder(x));   

注意:

1:BpxxxService類型為sp

2:BpBinder(x)相當(dāng)于xxxService對(duì)應(yīng)binder實(shí)體的代理

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

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

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

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

class BpxxxService : public BpInterface

{
    …

    vitural function(){
        Parcel data,reply;

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

        data.writeInt32(pid);

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

}

}

class BnxxxService: public BnInterface

{
    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()//自己實(shí)現(xiàn)的邏輯

break;

}

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

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

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

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

struct binder_state *bs;

void *svcmgr = BINDER_SERVICE_MANAGER;

bs = binder_open(128*1024);//應(yīng)該是打開(kāi)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第二個(gè)參數(shù)類型是IBinder 實(shí)例一個(gè)MediaPlayService也就是實(shí)例一個(gè)BnMediaPlaySerivce

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

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

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

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

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

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

其調(diào)用

sp t = new PoolThread(isMain);isMain是TRUE

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

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

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

    do {
        int32_tcmd;

        result =talkWithDriver();

        result =executeCommand(cmd);

     }

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

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

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

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

過(guò)程

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

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

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

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

代碼

如下是client獲取service的的代碼

第一步:

sp proc(ProcessState::self());

sp sm=defaultServiceManager();

見(jiàn)上

第二步:

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

sp sMediaPlayService =interface_cast(binder);

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


新聞標(biāo)題:Android中怎么利用Binder機(jī)制實(shí)現(xiàn)進(jìn)程間通信
URL鏈接:http://weahome.cn/article/ijhsgc.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部