角色: client 北滥、 service 昂勒、 serviceManager 井赌、Binder驅(qū)動
場景: 前三出演在用戶空間谤逼,后者在內(nèi)核空間作為幕后
劇本: a. client帶著“絕密級文件”需要跟神秘的service進(jìn)行會晤
b. client只知道service名字,但不知其人
c. service壓根就不知道有client會找她
后臺策劃1: 如下圖
劇場開幕: 基于以上劇本開演仇穗,
a. 由于業(yè)務(wù)發(fā)展client需要開展(調(diào)用)某項技能xx(方法)
b. 而這項技能掌握在server這種明星的手上
c. 由client(這種平民)直接要接觸到server流部,顯得太為不可能,那怎么拿到該項技能呢?
d. 代理纹坐,中間代理(就像租房中介)ta負(fù)責(zé)轉(zhuǎn)接“上與下(地位懸殊)”以及“租客與房東”此類關(guān)系的各種需求
e. proxy這里指的虛擬代理枝冀,真實(shí)代理還是binder負(fù)責(zé)
f. ?binder 在kernel 空間里為每一個進(jìn)程開辟了一塊用來做“黑交易(數(shù)據(jù)交互)”的內(nèi)存區(qū)(存放client 與 server 進(jìn)程處理的數(shù)據(jù))
智能的binder 為了提高“交易效率與數(shù)量”實(shí)現(xiàn)了一套機(jī)制,不僅為每個進(jìn)程創(chuàng)建一塊內(nèi)存區(qū)耘子,
此外 還“專門開辟了一塊共享內(nèi)存區(qū)用來存放處理完數(shù)據(jù)(以用來減少從kernel復(fù)制數(shù)據(jù)到用戶空間)” 見下面粉色(粉色粉色的)的圖
g. binder 對client來說果漾, 將請求打包成binder特有格式“paracel”傳輸?shù)?server
binder 對server來說,將client給到的請求進(jìn)行處理后谷誓,把結(jié)果包裝到paracel 送到binder 進(jìn)行發(fā)貨
i. ?client 可以選擇兩種方式來等待server處理結(jié)果: 阻塞(同步)一直專心致的等啊等跨晴,非阻塞(異步)提出了要求后,就不管了(跑了去干啥啥了)
h. 以上是每一次client ?通過 binder call method細(xì)節(jié)片林。
其實(shí)可總結(jié)為(“換做一種好理解的方式”)端盆,client通過binder 成功地獲取server對象實(shí)例的代理后怀骤,在本地任何操作就像是server親自發(fā)出指令一樣。
(這也是所謂的代理模式.... 姑且這么不恰當(dāng)理解&詮釋)焕妙,不服的(不服的來打架啊.....)
后臺策劃2:
劇場開演戲2: 基于策劃2開演
導(dǎo)演不滿意蒋伦,還要繼續(xù)BB.....
a. 例如client想要做一個“人生保健服務(wù)”但又不知道去哪里找店,于是打開手機(jī)輸入字段“人生保健服務(wù)”焚鹊,過了幾秒手機(jī)端就顯示了“周圍”(系統(tǒng)所具備的服務(wù))
b. 這里的ServicesManager將查詢結(jié)果(指向服務(wù)對象的類指針)返回給Client痕届,
c. ?Client 拿到“地址”踹緊口袋立馬打了一個滴滴屁顛顛的去店里做保健(向服務(wù)端call method,以期等待得到特定數(shù)據(jù))
d. ?Client怎么找到服務(wù)的呢末患? 原因是server早已在ServiceManager里面注冊自己的門店研叫,以等待顧客上門消費(fèi)
e. ?上面的一切都是在Binder地盤上完成交易,無奈他是老大璧针,提供了交易平臺(否則嚷炉,你以為隨隨便便就能找到保健店嗎,天真 ......)
劇終謝幕探橱,采訪幕后者“Binder”
在以上交易完成后申屹,請問
a. ?如何做到做好對接client 與server 的數(shù)據(jù)交互(通信傳輸)?
b. ?在系統(tǒng)里面面對多個client 有請求數(shù)據(jù)時隧膏,如何做到一一不落響應(yīng)每個客戶的請求哗讥?
c. ?binder掛掉了怎么辦?
以下統(tǒng)一回復(fù): ?謝謝 。
BpBinder對象:
a. ?客戶端通過它(IBinder)將數(shù)據(jù)請求傳達(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. ?再通過waitForResponse(reply) ?把mOut的數(shù)據(jù)通過ioctl發(fā)送給 binder驅(qū)動 ?, 并得到 驅(qū)動返回處理數(shù)據(jù). ? // 這里可設(shè)置等待方式(TF_ONE_WAY同步)
d. binder 只有一個文件描述符, ?系統(tǒng)里多客戶進(jìn)程同時執(zhí)行遠(yuǎn)程調(diào)用胞枕,并在ioctl上等待 處理結(jié)果杆煞, Android 如何保證其處理返回的數(shù)據(jù)能正確的交到正確的進(jìn)程呢?
這就是核心: "Android 在binder驅(qū)動里記錄每次binder調(diào)用信息(包含線程ID)腐泻,這樣根據(jù)ID可以知道將對應(yīng)的數(shù)據(jù)交給那個等待線程决乎,喚醒該進(jìn)程來讀取緩沖區(qū)數(shù)據(jù)"