Android 進(jìn)程間通信Binder原理

此文只是自己學(xué)習(xí)記錄慧邮,很籠統(tǒng)调限,沒學(xué)那么深舟陆,如有錯誤還請指正

1. Android 多線程通信概述

Android 系統(tǒng)是基于 Linux 內(nèi)核的,Linux 已經(jīng)提供了管道耻矮、消息隊(duì)列秦躯、共享內(nèi)存和 Socket 等 IPC 機(jī)制。那為什么 Android 還要提供 Binder 來實(shí)現(xiàn) IPC 呢踱承?主要是基于性能、穩(wěn)定性和安全性幾方面的原因哨免。

性能
首先說說性能上的優(yōu)勢茎活。Socket 作為一款通用接口,其傳輸效率低琢唾,開銷大载荔,主要用在跨網(wǎng)絡(luò)的進(jìn)程間通信和本機(jī)上進(jìn)程間的低速通信。消息隊(duì)列和管道采用存儲-轉(zhuǎn)發(fā)方式采桃,即數(shù)據(jù)先從發(fā)送方緩存區(qū)拷貝到內(nèi)核開辟的緩存區(qū)中懒熙,然后再從內(nèi)核緩存區(qū)拷貝到接收方緩存區(qū),至少有兩次拷貝過程普办。共享內(nèi)存雖然無需拷貝工扎,但控制復(fù)雜,難以使用泌豆。Binder 只需要一次數(shù)據(jù)拷貝定庵,性能上僅次于共享內(nèi)存蔬浙。

image.png

Binder優(yōu)勢匯總


image.png

Binder是怎么實(shí)現(xiàn)一次內(nèi)存拷貝的
Binder使用mmap技術(shù)實(shí)現(xiàn)了 接收進(jìn)程(用戶空間)緩存區(qū)到內(nèi)核空間緩存區(qū)的映射贞远,所以當(dāng)發(fā)送進(jìn)程通過系統(tǒng)調(diào)用將自己的數(shù)據(jù)copy到內(nèi)核空間時畴博,就相當(dāng)于直接copy到接收進(jìn)程的緩存中去,實(shí)現(xiàn)了一次copy蓝仲。

2. 多進(jìn)程通信的過程

Binder結(jié)構(gòu)下的多進(jìn)程通信少不了四個元素

  1. 內(nèi)核空間下的Binder驅(qū)動俱病,可以理解為Binder也是一個對象
  2. 守護(hù)進(jìn)程下的 ServerManager
  3. Client 進(jìn)程
  4. Server進(jìn)程

Binder 驅(qū)動
Binder 驅(qū)動就如同路由器一樣,是整個通信的核心袱结;驅(qū)動負(fù)責(zé)進(jìn)程之間 Binder 通信的建立,Binder 在進(jìn)程之間的傳遞,Binder 引用計數(shù)管理,數(shù)據(jù)包在進(jìn)程之間的傳遞和交互等一系列底層支持促王。

ServiceManager 與實(shí)名 Binder
ServiceManager 和 DNS 類似,作用是將字符形式的 Binder 名字轉(zhuǎn)化成 Client 中對該 Binder 的引用蝇狼,使得 Client 能夠通過 Binder 的名字獲得對 Binder 實(shí)體的引用阅畴。注冊了名字的 Binder 叫實(shí)名 Binder,就像網(wǎng)站一樣除了除了有 IP 地址意外還有自己的網(wǎng)址迅耘。Server 創(chuàng)建了 Binder冯事,并為它起一個字符形式,可讀易記得名字彰触,將這個 Binder 實(shí)體連同名字一起以數(shù)據(jù)包的形式通過 Binder 驅(qū)動發(fā)送給 ServiceManager ,通知 ServiceManager 注冊一個名為“張三”的 Binder,它位于某個 Server 中辉巡。驅(qū)動為這個穿越進(jìn)程邊界的 Binder 創(chuàng)建位于內(nèi)核中的實(shí)體節(jié)點(diǎn)以及 ServiceManager 對實(shí)體的引用,將名字以及新建的引用打包傳給 ServiceManager红氯。ServiceManger 收到數(shù)據(jù)后從中取出名字和引用填入查找表框咙。

細(xì)心的讀者可能會發(fā)現(xiàn)咕痛,ServierManager 是一個進(jìn)程,Server 是另一個進(jìn)程喇嘱,Server 向 ServiceManager 中注冊 Binder 必然涉及到進(jìn)程間通信茉贡。當(dāng)前實(shí)現(xiàn)進(jìn)程間通信又要用到進(jìn)程間通信,這就好像蛋可以孵出雞的前提卻是要先找只雞下蛋者铜!Binder 的實(shí)現(xiàn)比較巧妙腔丧,就是預(yù)先創(chuàng)造一只雞來下蛋。ServiceManager 和其他進(jìn)程同樣采用 Bidner 通信作烟,ServiceManager 是 Server 端愉粤,有自己的 Binder 實(shí)體,其他進(jìn)程都是 Client拿撩,需要通過這個 Binder 的引用來實(shí)現(xiàn) Binder 的注冊衣厘,查詢和獲取。ServiceManager 提供的 Binder 比較特殊压恒,它沒有名字也不需要注冊影暴。當(dāng)一個進(jìn)程使用 BINDERSETCONTEXT_MGR 命令將自己注冊成 ServiceManager 時 Binder 驅(qū)動會自動為它創(chuàng)建 Binder 實(shí)體(這就是那只預(yù)先造好的那只雞)。其次這個 Binder 實(shí)體的引用在所有 Client 中都固定為 0 而無需通過其它手段獲得探赫。也就是說型宙,一個 Server 想要向 ServiceManager 注冊自己的 Binder 就必須通過這個 0 號引用和 ServiceManager 的 Binder 通信。類比互聯(lián)網(wǎng)伦吠,0 號引用就好比是域名服務(wù)器的地址妆兑,你必須預(yù)先動態(tài)或者手工配置好。要注意的是毛仪,這里說的 Client 是相對于 ServiceManager 而言的搁嗓,一個進(jìn)程或者應(yīng)用程序可能是提供服務(wù)的 Server,但對于 ServiceManager 來說它仍然是個 Client箱靴。

Client 獲得實(shí)名 Binder 的引用
Server 向 ServiceManager 中注冊了 Binder 以后谱姓, Client 就能通過名字獲得 Binder 的引用了。Client 也利用保留的 0 號引用向 ServiceManager 請求訪問某個 Binder: 我申請訪問名字叫張三的 Binder 引用刨晴。ServiceManager 收到這個請求后從請求數(shù)據(jù)包中取出 Binder 名稱屉来,在查找表里找到對應(yīng)的條目,取出對應(yīng)的 Binder 引用作為回復(fù)發(fā)送給發(fā)起請求的 Client狈癞。從面向?qū)ο蟮慕嵌瓤辞芽浚琒erver 中的 Binder 實(shí)體現(xiàn)在有兩個引用:一個位于 ServiceManager 中,一個位于發(fā)起請求的 Client 中蝶桶。如果接下來有更多的 Client 請求該 Binder慨绳,系統(tǒng)中就會有更多的引用指向該 Binder ,就像 Java 中一個對象有多個引用一樣。

具體的通信過程如下

  1. 首先脐雪,一個進(jìn)程使用 BINDERSETCONTEXT_MGR 命令通過 Binder 驅(qū)動將自己注冊成為 ServiceManager厌小;
  2. Server 通過Binder驅(qū)動向 ServiceManager 中注冊 Binder(Server 中的 Binder 實(shí)體),表明可以對外提供服務(wù)战秋。驅(qū)動為這個 Binder 創(chuàng)建位于內(nèi)核中的實(shí)體節(jié)點(diǎn)以及 ServiceManager 對實(shí)體的引用璧亚,將名字以及新建的引用打包傳給 ServiceManager,ServiceManger 將其填入查找表脂信。
  3. Client 通過名字癣蟋,在 Binder 驅(qū)動的幫助下從 ServiceManager 中獲取到對 Binder 實(shí)體的引用,通過這個引用就能實(shí)現(xiàn)和 Server 進(jìn)程的通信狰闪。

現(xiàn)在我們可以對 Binder 做個更加全面的定義:

  1. 從進(jìn)程間通信的角度看疯搅,Binder 是一種進(jìn)程間通信的機(jī)制;
  2. 從 Server 進(jìn)程的角度看埋泵,Binder 指的是 Server 中的 Binder 實(shí)體對象幔欧;
  3. 從 Client 進(jìn)程的角度看,Binder 指的是對 Binder 代理對象丽声,是 Binder 實(shí)體對象的一個遠(yuǎn)程代理
  4. 從傳輸過程的角度看琐馆,Binder 是一個可以跨進(jìn)程傳輸?shù)膶ο螅籅inder 驅(qū)動會對這個跨越進(jìn)程邊界的對象對一點(diǎn)點(diǎn)特殊處理恒序,自動完成代理對象和本地對象之間的轉(zhuǎn)換。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谁撼,一起剝皮案震驚了整個濱河市歧胁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌厉碟,老刑警劉巖喊巍,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異箍鼓,居然都是意外死亡崭参,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進(jìn)店門款咖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來何暮,“玉大人,你說我怎么就攤上這事铐殃『M荩” “怎么了?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵富腊,是天一觀的道長坏逢。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么是整? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任肖揣,我火速辦了婚禮,結(jié)果婚禮上浮入,老公的妹妹穿的比我還像新娘龙优。我一直安慰自己,他們只是感情好舵盈,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布陋率。 她就那樣靜靜地躺著,像睡著了一般秽晚。 火紅的嫁衣襯著肌膚如雪瓦糟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天赴蝇,我揣著相機(jī)與錄音菩浙,去河邊找鬼。 笑死句伶,一個胖子當(dāng)著我的面吹牛劲蜻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播考余,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼先嬉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了楚堤?” 一聲冷哼從身側(cè)響起疫蔓,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎身冬,沒想到半個月后衅胀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡酥筝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年滚躯,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嘿歌。...
    茶點(diǎn)故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡掸掏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出宙帝,到底是詐尸還是另有隱情阅束,我是刑警寧澤,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布茄唐,位于F島的核電站息裸,受9級特大地震影響蝇更,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜呼盆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一年扩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧访圃,春花似錦厨幻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至批糟,卻和暖如春格了,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背徽鼎。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工盛末, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人否淤。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓悄但,卻偏偏與公主長得像,于是被迫代替她去往敵國和親石抡。 傳聞我的和親對象是個殘疾皇子檐嚣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評論 2 354

推薦閱讀更多精彩內(nèi)容