為什么選用Binder,在討論這個(gè)問題之前趣惠,我們知道Android也是基于Linux內(nèi)核狸棍,Linux現(xiàn)有的進(jìn)程通信手段有以下幾種:
- 管道:在創(chuàng)建時(shí)分配一個(gè)page大小的內(nèi)存身害,緩存區(qū)大小比較有限;
- 消息隊(duì)列:信息復(fù)制兩次草戈,額外的CPU消耗;不合適頻繁或信息量大的通信唐片;
- 共享內(nèi)存:無須復(fù)制丙猬,共享緩沖區(qū)直接附加到進(jìn)程虛擬地址空間,速度快牵触;但進(jìn)程間的同步問題操作系統(tǒng)無法實(shí)現(xiàn),必須各進(jìn)程利用同步工具解決咐低;
- 套接字:作為更通用的接口揽思,傳輸效率低,主要用于不同機(jī)器或跨網(wǎng)絡(luò)的通信见擦;
- 信號(hào)量:常作為一種鎖機(jī)制钉汗,防止某進(jìn)程正在訪問共享資源時(shí),其他進(jìn)程也訪問該資源鲤屡。因此损痰,主要作為進(jìn)程間以及同一進(jìn)程內(nèi)不同線程之間的同步手段。 不適用于信息交換酒来,更適用于進(jìn)程中斷控制卢未,比如非法內(nèi)存訪問,殺死某個(gè)進(jìn)程等堰汉;
既然有現(xiàn)有的IPC方式辽社,為什么重新設(shè)計(jì)一套Binder機(jī)制呢。主要是出于以上三個(gè)方面的考量:
-
效率:傳輸效率主要影響因素是內(nèi)存拷貝的次數(shù)翘鸭,拷貝次數(shù)越少滴铅,傳輸速率越高。從Android進(jìn)程架構(gòu)角度分析:對(duì)于消息隊(duì)列就乓、Socket和管道來說汉匙,數(shù)據(jù)先從發(fā)送方的緩存區(qū)拷貝到內(nèi)核開辟的緩存區(qū)中,再從內(nèi)核緩存區(qū)拷貝到接收方的緩存區(qū)生蚁,一共兩次拷貝噩翠,如圖:
1695c427354bbec4.jpg
而對(duì)于Binder來說,數(shù)據(jù)從發(fā)送方的緩存區(qū)拷貝到內(nèi)核的緩存區(qū)邦投,而接收方的緩存區(qū)與內(nèi)核的緩存區(qū)是映射到同一塊物理地址的绎秒,節(jié)省了一次數(shù)據(jù)拷貝的過程,如圖:
1695c428e3c4a95a.jpg
共享內(nèi)存不需要拷貝尼摹,Binder的性能僅次于共享內(nèi)存见芹。 - 穩(wěn)定性:上面說到共享內(nèi)存的性能優(yōu)于Binder剂娄,那為什么不采用共享內(nèi)存呢,因?yàn)楣蚕韮?nèi)存需要處理并發(fā)同步問題玄呛,容易出現(xiàn)死鎖和資源競爭阅懦,穩(wěn)定性較差。Socket雖然是基于C/S架構(gòu)的徘铝,但是它主要是用于網(wǎng)絡(luò)間的通信且傳輸效率較低耳胎。Binder基于C/S架構(gòu) ,Server端與Client端相對(duì)獨(dú)立惕它,穩(wěn)定性較好怕午。
- 安全性:傳統(tǒng)Linux IPC的接收方無法獲得對(duì)方進(jìn)程可靠的UID/PID,從而無法鑒別對(duì)方身份淹魄;而Binder機(jī)制為每個(gè)進(jìn)程分配了UID/PID郁惜,且在Binder通信時(shí)會(huì)根據(jù)UID/PID進(jìn)行有效性檢測。
Binder機(jī)制的作用和原理
Linux系統(tǒng)將一個(gè)進(jìn)程分為用戶空間和內(nèi)核空間甲锡。對(duì)于進(jìn)程之間來說兆蕉,用戶空間的數(shù)據(jù)不可共享,內(nèi)核空間的數(shù)據(jù)可共享缤沦,為了保證安全性和獨(dú)立性虎韵,一個(gè)進(jìn)程不能直接操作或者訪問另一個(gè)進(jìn)程,即Android的進(jìn)程是相互獨(dú)立缸废、隔離的包蓝,這就需要跨進(jìn)程之間的數(shù)據(jù)通信方式。普通的跨進(jìn)程通信方式一般需要2次內(nèi)存拷貝企量,如下圖所示:
一次完整的 Binder IPC 通信過程通常是這樣:
- 首先 Binder 驅(qū)動(dòng)在內(nèi)核空間創(chuàng)建一個(gè)數(shù)據(jù)接收緩存區(qū)养晋。
- 接著在內(nèi)核空間開辟一塊內(nèi)核緩存區(qū),建立內(nèi)核緩存區(qū)和內(nèi)核中數(shù)據(jù)接收緩存區(qū)之間的映射關(guān)系梁钾,以及內(nèi)核中數(shù)據(jù)接收緩存區(qū)和接收進(jìn)程用戶空間地址的映射關(guān)系绳泉。
- 發(fā)送方進(jìn)程通過系統(tǒng)調(diào)用 copyfromuser() 將數(shù)據(jù) copy 到內(nèi)核中的內(nèi)核緩存區(qū),由于內(nèi)核緩存區(qū)和接收進(jìn)程的用戶空間存在內(nèi)存映射姆泻,因此也就相當(dāng)于把數(shù)據(jù)發(fā)送到了接收進(jìn)程的用戶空間零酪,這樣便完成了一次進(jìn)程間的通信。
1695c1ab2efe8dc52.jpg
節(jié)選自:跨進(jìn)程通信