先上一張Binder 的工作流程圖驰坊。(如果不清晰,可以 復(fù)制圖片鏈接到瀏覽器 或 保存到本地 查看哮独,我經(jīng)常都是這樣看圖的哈)
一開(kāi)始上手拳芙,陌生的東西比較多,But皮璧,其實(shí)并不復(fù)雜态鳖。喔,流程圖是用 ProcessOn 畫(huà)的恶导。很棒的在線畫(huà)圖工具。
出發(fā)前預(yù)備子彈
我們知道進(jìn)程之間浸须,虛擬地址不同惨寿,是不能直接通信的,這是一種保護(hù)機(jī)制删窒。打開(kāi)任務(wù)管理器裂垦,查看一下N多的進(jìn)程,試想一下如果這些進(jìn)程直接通信會(huì)帶來(lái)什么后果肌索?
而用戶空間可以通過(guò)System calls(系統(tǒng)回調(diào))與內(nèi)核空間通信的蕉拢,如果在內(nèi)核空間中有一個(gè)模塊,能夠完成數(shù)據(jù)的轉(zhuǎn)發(fā),那么是不是兩個(gè)進(jìn)程就可以通信了呢晕换?如下圖:
上面提到一些用戶空間午乓、內(nèi)核空間的概念,用戶空間也能大概猜到是什么東西闸准,而內(nèi)核空間益愈,就知道它是很底層的東西好了。而模塊呢夷家,可以簡(jiǎn)單的理解為實(shí)現(xiàn)一個(gè)功能的程序或一個(gè)硬件電路等蒸其,比如玩單片機(jī)的時(shí)候,會(huì)有紅外線模塊库快,藍(lán)牙模塊摸袁,wifi模塊等。這些概念的東西搜索一下百科知道就好义屏。
Binder驅(qū)動(dòng)
Binder驅(qū)動(dòng)運(yùn)行在內(nèi)核空間靠汁,它就是那個(gè)內(nèi)核模塊了。Binder驅(qū)動(dòng)很重要湿蛔,承擔(dān)了進(jìn)程間通信的數(shù)據(jù)轉(zhuǎn)發(fā)等膀曾。一提到驅(qū)動(dòng),也是比較熟悉阳啥,你插個(gè)U盤(pán)添谊,需要驅(qū)動(dòng)吧。而B(niǎo)inder驅(qū)動(dòng)也差不多察迟,雖然名字取得很好斩狱,功能還很強(qiáng)大。但也不是什么神奇的東西扎瓶。
Binder跨進(jìn)程通信模型
Binder的通信模型有4個(gè)角色:Binder Client所踊、Binder Server、Binder Driver(Binder驅(qū)動(dòng))概荷、ServiceManager秕岛。
想象一個(gè)情景:我到北京旅行,要給高中同學(xué)寄一張明信片误证,明信片肯定要寫(xiě)上地址吧继薛,不然怎么寄給對(duì)方呢?那么我怎么拿到這個(gè)地址呢愈捅,很簡(jiǎn)單遏考,翻一下畢業(yè)相冊(cè)就好了。而這個(gè)記錄著同學(xué)們通信地址的畢業(yè)相冊(cè)蓝谨,就相當(dāng)與一個(gè)通訊錄灌具。在Binder的通信模型中扮演的是ServiceManager的角色青团。好,現(xiàn)在已經(jīng)有了通信地址了咖楣,那么就找到郵局寄出去就好了督笆。過(guò)幾天同學(xué)就高高興興的收到了明信片。那么這個(gè)郵局在Binder通信模型中扮演的是Binder驅(qū)動(dòng)的角色截歉,而作為寄信人的我就是Binder Client胖腾,收信人同學(xué)就是Binder Server。
先上一張圖來(lái)描述上面的那個(gè)情景:
可以看到瘪松,ServiceManager咸作、Binder Client、Binder Server處于不同的進(jìn)程宵睦,他們?nèi)齻€(gè)都在用戶空間记罚,而B(niǎo)inder驅(qū)動(dòng)在內(nèi)核空間。(我是特意把Binder驅(qū)動(dòng)畫(huà)的比較大的壳嚎,因?yàn)锽inder驅(qū)動(dòng)的作用最大)
那先來(lái)簡(jiǎn)述一下這個(gè)通信模型:
首先是有一個(gè)ServiceManager桐智,剛開(kāi)始這個(gè)通訊錄是空白的,然后Server進(jìn)程向ServiceManager注冊(cè)一個(gè)映射關(guān)系表烟馅,比如徐同學(xué)把自己的地址廣東省廣州市xx區(qū)寫(xiě)進(jìn)通訊錄说庭,那么就形成了一張表:
徐同學(xué) —> 廣東省廣州市xx區(qū)
之后Client進(jìn)程想要和Server進(jìn)程通信,首先向ServiceManager查詢(xún)地址郑趁,ServiceManager收到查詢(xún)的請(qǐng)求之后刊驴,返回查詢(xún)結(jié)果給Client。
注意到這里不管是Server進(jìn)程注冊(cè)寡润,還是Client查詢(xún)捆憎,都是經(jīng)過(guò)Binder驅(qū)動(dòng)的,這也真是Binder驅(qū)動(dòng)的作用所在梭纹,先不急躲惰,下面的原理會(huì)分析到。
這時(shí)候我就拿著地址就開(kāi)始寄明信片咯变抽。當(dāng)我把明信片放扔進(jìn)郵筒础拨,之后的工作就是由郵局去完成了,也就是Binder驅(qū)動(dòng)去完成通信的轉(zhuǎn)發(fā)绍载。
Binder通信原理
從寄明信片的例子中太伊,郵遞員從郵筒取出明信片,然后跨越千山萬(wàn)水將明信片送達(dá)逛钻。從這點(diǎn)我們也能想到,其實(shí)Binder驅(qū)動(dòng)完成的工作是很重要的锰提。
我們來(lái)還原一個(gè)Binder跨進(jìn)程通信的過(guò)程曙痘。 案例:Client進(jìn)程調(diào)用Server進(jìn)程的computer對(duì)象的add方法芳悲。
接下來(lái)的內(nèi)容你可能需要知道代理模式才能更好的理解,不過(guò)沒(méi)學(xué)習(xí)過(guò)代理模式也沒(méi)關(guān)系边坤,可以先讀下去名扛,然后在去補(bǔ)一下代理模式,再回來(lái)看這篇文章茧痒。思路會(huì)清晰很多肮韧。
1. Server進(jìn)程向ServiceManager注冊(cè),告訴ServiceManager我是誰(shuí)旺订,我有什么弄企,我能做什么。就好比徐同學(xué)(Server進(jìn)程)有一臺(tái)筆記本(computer對(duì)象)区拳,這臺(tái)筆記本有個(gè)add方法拘领。這時(shí)映射關(guān)系表就生成了。
2. Client進(jìn)程向ServiceManager查詢(xún)樱调,我要調(diào)用Server進(jìn)程的computer對(duì)象的add方法约素,可以看到這個(gè)過(guò)程經(jīng)過(guò)Binder驅(qū)動(dòng),這時(shí)候Binder驅(qū)動(dòng)就開(kāi)始發(fā)揮他的作用了笆凌。
當(dāng)向ServiceManager查詢(xún)完畢圣猎,是返回一個(gè)computer對(duì)象給Client進(jìn)程嗎?其實(shí)不然乞而,Binder驅(qū)動(dòng)將computer對(duì)象轉(zhuǎn)換成了computerProxy對(duì)象送悔,并轉(zhuǎn)發(fā)給了Client進(jìn)程,
因此晦闰,Client進(jìn)程拿到的并不是真實(shí)的computer對(duì)象放祟,而是一個(gè)代理對(duì)象,即computerProxy對(duì)象呻右。很容易理解這個(gè)computerProxy對(duì)象也是有add方法跪妥,(如果連add方法都沒(méi)有,豈不是欺騙了Client声滥?)眉撵,但是這個(gè)add方法只是對(duì)參數(shù)進(jìn)行一些包裝而已。
3. 當(dāng)Client進(jìn)程調(diào)用add方法落塑,這個(gè)消息發(fā)送給Binder驅(qū)動(dòng)纽疟,這時(shí)驅(qū)動(dòng)發(fā)現(xiàn),原來(lái)是computerProxy憾赁,那么Client進(jìn)程應(yīng)該是需要調(diào)用computer對(duì)象的add方法的污朽,這時(shí)驅(qū)動(dòng)通知Server進(jìn)程,調(diào)用你的computer對(duì)象的add方法龙考,將結(jié)果給我蟆肆。
然后Server進(jìn)程就將計(jì)算結(jié)果發(fā)送給驅(qū)動(dòng)矾睦,驅(qū)動(dòng)再轉(zhuǎn)發(fā)給Client進(jìn)程,這時(shí)Client進(jìn)程還蒙在了鼓里炎功,他以為自己調(diào)用的是真實(shí)的computer對(duì)象的add方法枚冗,其實(shí)他只是調(diào)用了代理而已。不過(guò)Client最終還是拿到了計(jì)算結(jié)果蛇损。
好了赁温,一個(gè)通信過(guò)程就完成了。我們發(fā)現(xiàn)淤齐,其實(shí)Binder驅(qū)動(dòng)就是一個(gè)中轉(zhuǎn)股囊。
總結(jié)
再來(lái)梳理總結(jié)一下:當(dāng)Client進(jìn)程向ServiceManager查詢(xún)Server進(jìn)程(我要調(diào)用你的某個(gè)對(duì)象的某個(gè)方法了),這個(gè)過(guò)程也是一個(gè)跨進(jìn)程通信的過(guò)程床玻,也經(jīng)過(guò)了Binder驅(qū)動(dòng)毁涉,這時(shí)Binder驅(qū)動(dòng)發(fā)揮它的作用,來(lái)了個(gè)貍貓換太子锈死,將Server進(jìn)程中的真實(shí)對(duì)象轉(zhuǎn)換成代理對(duì)象贫堰,返回這個(gè)代理對(duì)象給Client進(jìn)程。
Client進(jìn)程拿到了這個(gè)代理對(duì)象待牵,然后調(diào)用這個(gè)代理對(duì)象的方法其屏,Binder驅(qū)動(dòng)繼續(xù)發(fā)揮他的使命,它會(huì)通知Server進(jìn)程執(zhí)行計(jì)算工作缨该,將Server進(jìn)程中的真實(shí)對(duì)象執(zhí)行的結(jié)果返回給了Client進(jìn)程偎行,這樣Client進(jìn)程還是如愿的得到了自己想要》∧茫跨進(jìn)程通信完畢蛤袒!
這篇文章寫(xiě)的主要是我學(xué)習(xí)Binder時(shí)的痛點(diǎn),我看過(guò)好多篇講Binder的文章膨更,發(fā)現(xiàn)好多都是不講Binder驅(qū)動(dòng)的妙真,我很懵逼為什么那么重要的東西就略過(guò),但還是有大神寫(xiě)的很好荚守,比如:
Binder學(xué)習(xí)指南
Android Binder設(shè)計(jì)與實(shí)現(xiàn)