角色: client 、 service 、 serviceManager 、Binder驅(qū)動(dòng)
場(chǎng)景: 前三出演在用戶空間,后者在內(nèi)核空間作為幕后
劇本: a. client帶著“絕密級(jí)文件”需要跟神秘的service進(jìn)行會(huì)晤
b. client只知道service名字,但不知其人
c. service壓根就不知道有client會(huì)找她
后臺(tái)策劃1: 如下圖

劇場(chǎng)開(kāi)幕: 基于以上劇本開(kāi)演,
a. 由于業(yè)務(wù)發(fā)展client需要開(kāi)展(調(diào)用)某項(xiàng)技能xx(方法)
b. 而這項(xiàng)技能掌握在server這種明星的手上
c. 由client(這種平民)直接要接觸到server,顯得太為不可能,那怎么拿到該項(xiàng)技能呢?
d. 代理,中間代理(就像租房中介)ta負(fù)責(zé)轉(zhuǎn)接“上與下(地位懸殊)”以及“租客與房東”此類關(guān)系的各種需求
e. proxy這里指的虛擬代理,真實(shí)代理還是binder負(fù)責(zé)
f. ?binder 在kernel 空間里為每一個(gè)進(jìn)程開(kāi)辟了一塊用來(lái)做“黑交易(數(shù)據(jù)交互)”的內(nèi)存區(qū)(存放client 與 server 進(jìn)程處理的數(shù)據(jù))
智能的binder 為了提高“交易效率與數(shù)量”實(shí)現(xiàn)了一套機(jī)制,不僅為每個(gè)進(jìn)程創(chuàng)建一塊內(nèi)存區(qū),
此外 還“專門(mén)開(kāi)辟了一塊共享內(nèi)存區(qū)用來(lái)存放處理完數(shù)據(jù)(以用來(lái)減少?gòu)膋ernel復(fù)制數(shù)據(jù)到用戶空間)” 見(jiàn)下面粉色(粉色粉色的)的圖
g. binder 對(duì)client來(lái)說(shuō), 將請(qǐng)求打包成binder特有格式“paracel”傳輸?shù)?server
binder 對(duì)server來(lái)說(shuō),將client給到的請(qǐng)求進(jìn)行處理后,把結(jié)果包裝到paracel 送到binder 進(jìn)行發(fā)貨
i. ?client 可以選擇兩種方式來(lái)等待server處理結(jié)果: 阻塞(同步)一直專心致的等啊等,非阻塞(異步)提出了要求后,就不管了(跑了去干啥啥了)
h. 以上是每一次client ?通過(guò) binder call method細(xì)節(jié)。
其實(shí)可總結(jié)為(“換做一種好理解的方式”),client通過(guò)binder 成功地獲取server對(duì)象實(shí)例的代理后,在本地任何操作就像是server親自發(fā)出指令一樣。
(這也是所謂的代理模式.... 姑且這么不恰當(dāng)理解&詮釋),不服的(不服的來(lái)打架啊.....)

后臺(tái)策劃2:

劇場(chǎng)開(kāi)演戲2: 基于策劃2開(kāi)演
導(dǎo)演不滿意,還要繼續(xù)BB.....
a. 例如client想要做一個(gè)“人生保健服務(wù)”但又不知道去哪里找店,于是打開(kāi)手機(jī)輸入字段“人生保健服務(wù)”,過(guò)了幾秒手機(jī)端就顯示了“周?chē)保ㄏ到y(tǒng)所具備的服務(wù))
b. 這里的ServicesManager將查詢結(jié)果(指向服務(wù)對(duì)象的類指針)返回給Client,
c. ?Client 拿到“地址”踹緊口袋立馬打了一個(gè)滴滴屁顛顛的去店里做保健(向服務(wù)端call method,以期等待得到特定數(shù)據(jù))
d. ?Client怎么找到服務(wù)的呢? 原因是server早已在ServiceManager里面注冊(cè)自己的門(mén)店,以等待顧客上門(mén)消費(fèi)
e. ?上面的一切都是在Binder地盤(pán)上完成交易,無(wú)奈他是老大,提供了交易平臺(tái)(否則,你以為隨隨便便就能找到保健店嗎,天真 ......)
劇終謝幕,采訪幕后者“Binder”
在以上交易完成后,請(qǐng)問(wèn)
a. ?如何做到做好對(duì)接client 與server 的數(shù)據(jù)交互(通信傳輸)?
b. ?在系統(tǒng)里面面對(duì)多個(gè)client 有請(qǐng)求數(shù)據(jù)時(shí),如何做到一一不落響應(yīng)每個(gè)客戶的請(qǐng)求?
c. ?binder掛掉了怎么辦?
以下統(tǒng)一回復(fù): ?謝謝 。
BpBinder對(duì)象:
a. ?客戶端通過(guò)它(IBinder)將數(shù)據(jù)請(qǐng)求傳達(dá)到Server端
BpBinder::transact(code ,Paracel&data,Paracel*reply, flags )
b. 緊接著IPCThreadState::transact(handle , code , Parcel &data , Paracel *reply , flags )收到命令立即將數(shù)據(jù)
裝入mOut變量里 (viawriteTransactionData(BC_TRANSACTION,flags , handle , code , data , NULL))
c. ?再通過(guò)waitForResponse(reply) ?把mOut的數(shù)據(jù)通過(guò)ioctl發(fā)送給 binder驅(qū)動(dòng) ?, 并得到 驅(qū)動(dòng)返回處理數(shù)據(jù). ? // 這里可設(shè)置等待方式(TF_ONE_WAY同步)
d. binder 只有一個(gè)文件描述符, ?系統(tǒng)里多客戶進(jìn)程同時(shí)執(zhí)行遠(yuǎn)程調(diào)用,并在ioctl上等待 處理結(jié)果, Android 如何保證其處理返回的數(shù)據(jù)能正確的交到正確的進(jìn)程呢?
這就是核心: "Android 在binder驅(qū)動(dòng)里記錄每次binder調(diào)用信息(包含線程ID),這樣根據(jù)ID可以知道將對(duì)應(yīng)的數(shù)據(jù)交給那個(gè)等待線程,喚醒該進(jìn)程來(lái)讀取緩沖區(qū)數(shù)據(jù)"