1 為什么需要跨進(jìn)程通信
首先同一個(gè)程序中之所以兩個(gè)函數(shù)之間能夠直接調(diào)用喉前,其根本原因是它們處于相同的內(nèi)存空間中,虛擬地址的映射規(guī)則完全一致轻专。反之不同進(jìn)程之間它們沒辦法通過內(nèi)存地址來直接訪問到對(duì)方內(nèi)部的函數(shù)或者變量忆矛。
2 為什么采用Binder
常用的IPC機(jī)制有管道、Socket请垛、共享內(nèi)存等催训,那么Android中為什么要建立一套新的IPC機(jī)制?
1 開銷問題
socket作為一款通用接口宗收,其傳輸效率低漫拭,開銷大,主要用在跨網(wǎng)絡(luò)的進(jìn)程間通信和本機(jī)上進(jìn)程間的低速通信混稽。消息隊(duì)列和管道采用存儲(chǔ)-轉(zhuǎn)發(fā)方式采驻,即數(shù)據(jù)先從發(fā)送方緩存區(qū)拷貝到內(nèi)核開辟的緩存區(qū)中,然后再從內(nèi)核緩存區(qū)拷貝到接收方緩存區(qū)匈勋,至少有兩次拷貝過程礼旅。共享內(nèi)存雖然無需拷貝,但控制復(fù)雜颓影,難以使用。
2 安全問題
傳統(tǒng)IPC沒有任何安全措施懒鉴,完全依賴上層協(xié)議來確保诡挂。首先傳統(tǒng)IPC的接收方無法獲得對(duì)方進(jìn)程可靠的UID和PID(用戶ID進(jìn)程ID),從而無法鑒別對(duì)方身份临谱。Android為每個(gè)安裝好的應(yīng)用程序分配了自己的UID璃俗,故進(jìn)程的UID是鑒別進(jìn)程身份的重要標(biāo)志。使用傳統(tǒng)IPC只能由用戶在數(shù)據(jù)包里填入U(xiǎn)ID和PID悉默,但這樣不可靠城豁,容易被惡意程序利用〕危可靠的身份標(biāo)記只有由IPC機(jī)制本身在內(nèi)核中添加唱星。其次傳統(tǒng)IPC訪問接入點(diǎn)是開放的雳旅,無法建立私有通道。比如命名管道的名稱间聊,systemV的鍵值攒盈,socket的ip地址或文件名都是開放的,只要知道這些接入點(diǎn)的程序都可以和對(duì)端建立連接哎榴,不管怎樣都無法阻止惡意程序通過猜測(cè)接收方地址獲得連接型豁。
基于以上原因,Android需要建立一套新的IPC機(jī)制來滿足系統(tǒng)對(duì)通信方式尚蝌,傳輸性能和安全性的要求迎变,這就是Binder。Binder基于Client-Server通信模式飘言,傳輸過程只需一次拷貝衣形,為發(fā)送發(fā)添加UID/PID身份,既支持實(shí)名Binder也支持匿名Binder热凹,安全性高泵喘。
3 Binder跨進(jìn)程通信原理
mmap()的返回值是內(nèi)存映射在用戶空間的地址,不過這段空間是由驅(qū)動(dòng)管理般妙,用戶不必也不能直接訪問(映射類型為PROT_READ纪铺,只讀映射)。進(jìn)程A通過copy_from_user()將數(shù)據(jù)拷貝到binder_proc->buffer所指向的內(nèi)存空間中碟渺,而因?yàn)閎inder_proc->buffer在物理內(nèi)存中的位置和進(jìn)程B是共享的鲜锚,因此進(jìn)程B可以直接訪問到這段數(shù)據(jù),從而實(shí)現(xiàn)了進(jìn)程間的數(shù)據(jù)共享苫拍。