前言
Binder是android中一個(gè)很重要且很復(fù)雜的概念,它在系統(tǒng)的整體運(yùn)作中發(fā)揮著極其重要的作用纳账,它是Android中的一種跨進(jìn)程通信方式。
為什么Android內(nèi)核要使用Binder
Android中有大量的CS(Client-Server)應(yīng)用方式,這就要求Android內(nèi)部提供IPC方法震糖,而linux所支持的進(jìn)程通信方式有兩個(gè)問題:性能和安全性。
目前l(fā)inux支持的IPC包括傳統(tǒng)的管道趴腋,System V IPC(消息隊(duì)列/共享內(nèi)存/信號(hào)量)吊说,以及socket,但只有socket支持Client-Server的通信方式优炬,由于socket是一套通用的網(wǎng)絡(luò)通信方式颁井,其傳輸效率低下切有很大的開銷,比如socket的連接建立過程和中斷連接過程都是有一定開銷的蠢护。消息隊(duì)列和管道采用存儲(chǔ)-轉(zhuǎn)發(fā)方式雅宾,即數(shù)據(jù)先從發(fā)送方緩存區(qū)拷貝到內(nèi)核開辟的緩存區(qū)中,然后再從內(nèi)核緩存區(qū)拷貝到接收方緩存區(qū)葵硕,至少有兩次拷貝過程眉抬。共享內(nèi)存雖然無需拷貝,但控制復(fù)雜懈凹,難以使用吐辙。
而Binder基于 Client-Server通信模式,傳輸過程只需一次拷貝蘸劈。
在安全性方面昏苏,傳統(tǒng)IPC沒有任何安全措施,完全依賴上層協(xié)議來確保。而Android為每個(gè)安裝好的應(yīng)用程序分配了自己的UID贤惯,可靠的身份標(biāo)記只有由IPC機(jī)制本身在內(nèi)核中添加洼专。
基于以上原因,Android需要建立一套新的IPC機(jī)制來滿足系統(tǒng)對通信方式孵构,傳輸性能和安全性的要求屁商,這就是Binder。
Binder通信原理:
Binder基于 Client-Server通信模式颈墅,傳輸過程只需一次拷貝蜡镶,為發(fā)送發(fā)添加UID/PID身份,既支持實(shí)名Binder也支持匿名Binder恤筛,包含角色:Server端A官还、Client端B、Binder驅(qū)動(dòng)毒坛、內(nèi)核空間望伦、物理內(nèi)存、ServiceManager
步驟 | 描述 | 說明 |
---|---|---|
注冊服務(wù) | 1煎殷、Server進(jìn)程向binder驅(qū)動(dòng)發(fā)起服務(wù)注冊請求屯伞。2、Binder驅(qū)動(dòng)將注冊請求轉(zhuǎn)發(fā)給ServerManager進(jìn)程豪直。3劣摇、ServerManager進(jìn)程添加該Server進(jìn)程 | 此時(shí)ServerManager進(jìn)程擁有了Server進(jìn)程的信息 |
獲取服務(wù) | 1、Client向Binder發(fā)起獲取服務(wù)的請求傳遞要獲取的服務(wù)名稱弓乙。2末融、Binder驅(qū)動(dòng)將該請求轉(zhuǎn)發(fā)到ServerManager進(jìn)程。 3唆貌、ServerManager查找到Client需要的Server對應(yīng)的服務(wù)信息。4垢乙、通過Binder驅(qū)動(dòng)將上述服務(wù)信息返回給Client進(jìn)程 | 此時(shí)Clinet進(jìn)程與Server進(jìn)程已建立了連接 |
注冊服務(wù)過程:
第一步: service通過調(diào)用serviceManager中的addService方法锨咙,然后調(diào)用ServiceManagerNative類中的addservice(name)方法。
第二步: ServiceManagerNative會(huì)通過Binder發(fā)送一條SVG_MGR_ADD_SERVICE的指令追逮,然后通過svcmgr_handler()調(diào)用do_add_service()方法往svc_list中添加相應(yīng)的service
獲取服務(wù)過程:
第一步:client要請求服務(wù)酪刀,比如說在activity中調(diào)用context.getSystemService()方法,這個(gè)時(shí)候serviceManager就會(huì)使用getService(name)钮孵,然后就會(huì)調(diào)用到native層中的ServiceManagerNative類中的getService(name)方法骂倘。
第二步:ServiceManagerNative會(huì)通過Binder發(fā)送一條SVG_MGR_GET_SERVICE的指令,然后通過svcmgr_handler()調(diào)用do_find_service()方法去svc_list中查找到相關(guān)的service巴席。
第三步:查找到相應(yīng)的服務(wù)后就會(huì)通過Binder將服務(wù)傳給ServiceManagerNative历涝,然后傳給serviceManager,最后client就可以使用了。
ServiceManager也是一個(gè)單獨(dú)的進(jìn)程荧库,那Server堰塌、Client如何與ServiceManager進(jìn)行通信呢?
實(shí)際上Client分衫、Server场刑、ServiceManager之間都是依靠Binder通信,只是ServiceManager作為特殊的Binder(handle=0)提前放入了Binder驅(qū)動(dòng)里蚪战,當(dāng)Client牵现、Server想要獲取ServiceManager的Binder引用,只需要獲取handle=0的Binder即可邀桑。
Binder驅(qū)動(dòng)在物理內(nèi)存中開辟一塊固定大邢固邸(1M-8K)的物理內(nèi)存w,與內(nèi)核空間的虛擬地址x進(jìn)行映射得到
A的用戶空間的虛擬地址ax和物理內(nèi)存w進(jìn)行映射
此時(shí)內(nèi)核空間虛擬地址x和物理內(nèi)存w已經(jīng)進(jìn)行了映射概漱,物理內(nèi)存w和Server端A的用戶空間虛擬地址ax進(jìn)行了映射:也就是 內(nèi)核空間的虛擬地址x = 物理內(nèi)存w = Server端A的用戶空間虛擬地址ax
B發(fā)送請求:將數(shù)據(jù)按照binder協(xié)議進(jìn)行打包給到Binder驅(qū)動(dòng)丑慎,Binder驅(qū)動(dòng)調(diào)用coay_from_user()將數(shù)據(jù)拷貝到內(nèi)核空間的虛擬地址x
因步驟3中的三塊區(qū)域進(jìn)行了映射
Server端A就得到了Client端B發(fā)送的數(shù)據(jù)
通過內(nèi)存映射關(guān)系,只發(fā)生了一次拷貝
Activity跳轉(zhuǎn)時(shí)瓤摧,最多攜帶1M-8k(1兆減去8K)的數(shù)據(jù)量竿裂;真實(shí)數(shù)據(jù)大小為:1M內(nèi)存-兩頁的請求頭數(shù)據(jù)=1M-8K;
流程:
每個(gè)App進(jìn)程啟動(dòng)時(shí)會(huì)在內(nèi)核空間中映射一塊1M-8K的內(nèi)存
服務(wù)端A的服務(wù)注冊到ServiceManager中:服務(wù)注冊
客戶端B想要調(diào)用服務(wù)端A的服務(wù)照弥,就去請求ServiceManager
ServiceManager去讓服務(wù)端A實(shí)例化服務(wù):服務(wù)發(fā)現(xiàn)
返回一個(gè)用來發(fā)送數(shù)據(jù)的對象BpBinder給到客戶端B
客戶端B通過BpBinder發(fā)送數(shù)據(jù)到服務(wù)端A的內(nèi)核的映射區(qū)域(傳參時(shí)客戶端會(huì)傳一個(gè)reply序列化對象腻异,在底層會(huì)將這個(gè)地址一層一層往下傳,直至傳到回調(diào)客戶端):這里發(fā)生了一次通信copy_from_user:服務(wù)調(diào)用
服務(wù)端A通過BBBinder得到數(shù)據(jù)并處理數(shù)據(jù)
服務(wù)端喚醒客戶端等待的線程这揣;將返回結(jié)果寫入到客戶端發(fā)送請求時(shí)傳的一個(gè)reply容器地址中,調(diào)用onTransact返回悔常;
客戶端在onTransac中得到數(shù)據(jù);通信結(jié)束给赞;
ServiceManager維持了Binder這套通信框架机打;