這篇文章給大家介紹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
sp
第二步:
defaultServiceManager()->addService(String16("media.player"),new MediaPlayerService());
第三步:
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
代碼分析
sp
創(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
主要執(zhí)行如下代碼
sp
其中PorcessState::self()->getContextObject(NULL)就是執(zhí)行PorcessState::getStrongProxyForHandle(0);其主要是根據(jù)給定的參數(shù)(此處為0)創(chuàng)建對(duì)應(yīng)的sp
這邊先說(shuō)明interface_case這個(gè)模版類,這個(gè)模版類作用是將服務(wù)xxxService對(duì)應(yīng)的BpBinder(x)轉(zhuǎn)化為對(duì)應(yīng)的BpxxxService如下:
sp
其本質(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
其中用宏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
由此得到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)于sp
return new BpxxxService
}
當(dāng)有這個(gè)服務(wù)的Bpbinder(x)后可通過(guò)如下獲取BpxxxService
sp
注意:
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
下面分析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->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
這里面會(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ò)sp
第三步:訪問(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
sp
見(jiàn)上
第二步:
sp
sp
關(guān)于Android中怎么利用Binder機(jī)制實(shí)現(xiàn)進(jìn)程間通信就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。