Binder

HandKnock發表於2020-10-29

Binder

核心空間
使用者空間
binder講清楚
https://juejin.im/post/6844903656131657736
一次拷貝:記憶體對映mmap
安全,有身份驗證uid
C/S架構

  • 是APP和系統服務之間的通訊工具,提供跨程式的訊息傳遞。
  • 系統的核心空間是共享的,每個程式都可以訪問,Binder驅動存在於核心空間
  • 每一個程式都有一個ProcessState物件,負責開啟Binder驅動
  • 每一個執行緒都有一個IPCThreadState物件,通過talkWithDriver,將IPC資料寫入驅動中

IPC資料,包含的指令資訊會說明,我是要和Server端哪個service打交道,請連線它,並把我要給它的東西給它,我要它乾的事情告訴它

Binder驅動有連線著Server所有的service能力,具體是怎麼實現的

好像是通過ServiceManager啟動之後,啟動迴圈,處理Client端發過來的請求

跨程式方式

傳統的Linux跨程式方式:管道,共享記憶體,socket

  • 通訊不安全:因為Linux核心不存在一種校驗雙方身份的機制,android為每個APP分配了UID,是鑑別程式身份的重要標誌,在核心中新增。傳統的IPC由使用者在資料包填入UID/PID,容易篡改
  • 穩定性好:基於C/S架構
  • 效能:socket傳輸效率低,開銷大;管道採用儲存/轉發方式,至少2次拷貝;Binder只需要一次拷貝,效能僅次於共享記憶體

應用層方式

主要有intent,只支援Bundle支援的資料型別;
Messenger 支援一對多序列通訊,用於傳送訊息及Bundle資料;
AIDL 功能強大,可呼叫服務端方法;
ContentProvider 主要支援程式間共享資料;
BroadCastReceiver 廣播也可實現程式間通訊,傳送訊息及資料

穩定性:上面說到共享記憶體的效能優於Binder,那為什麼不採用共享記憶體呢,因為共享記憶體需要處理併發同步問題,容易出現死鎖和資源競爭,穩定性較差。Socket雖然是基於C/S架構的,但是它主要是用於網路間的通訊且傳輸效率較低。Binder基於C/S架構 ,Server端與Client端相對獨立,穩定性較好

當有多個業務模組都需要AIDL來進行IPC,此時需要為每個模組建立特定的aidl檔案,那麼相應的Service就會很多。必然會出現系統資源耗費嚴重、應用過度重量級的問題。解決辦法是建立Binder連線池,即將每個業務模組的Binder請求統一轉發到一個遠端Service中去執行,從而避免重複建立Service。
工作原理:每個業務模組建立自己的AIDL介面並實現此介面,然後向服務端提供自己的唯一標識和其對應的Binder物件。服務端只需要一個Service並提供一個queryBinder介面,它會根據業務模組的特徵來返回相應的Binder物件,不同的業務模組拿到所需的Binder物件後就可以進行遠端方法的呼叫了。

程式隔離:程式和程式間記憶體是不共享的,要通訊

https://blog.csdn.net/pange1991/article/details/84770181//作業系統程式的分配
https://juejin.im/post/5acccf845188255c3201100f//使用者態和核心態

AIDL

我們來講一下AIDL,它是Binder的封裝JAVA API,應用層想要和Server端通訊就可以直接使用AIDL了

AIDL支援的資料型別

基本資料型別(int、long、char 等)
String 和 CharSequence
List:只支援ArrayList,裡面的每個元素都必須被AIDL支援。
Map: 只支援HashMap, 裡面的每個元素都必須被AIDL支援。
Parcelable: 所有實現了Parcelable介面的物件
AIDL: 所有的AIDL介面本身也可以在AIDL檔案中使用

server端

1、建立aidl檔案aa.aidl,build之後在build/generated/source/aidl/debug路徑生成aa.java,包含了一個抽象的內部類:stub,繼承自Binder實現了aa介面,在stub內部,又建立了一個靜態內部類Proxy,也實現了aa介面
然後
2、然後定義一個service,重寫onBind方法

client端

1、將server端的aidl檔案copy到client相同路徑資料夾下,build生成java檔案
bindService(intent,connection,Context.BIND_AUTO_CREATE),繫結成功之後,拿到server端傳回的Binder物件,就可以呼叫到aa介面方法了

原理
asInterface(IBinder obj),將Binder物件轉換成aa物件

1、client和server在同一個程式,直接返回stub物件,強轉成aa物件,呼叫aa.aa()方法
2、client和server不是同一個程式,返回代理類prxoy物件。強轉成aa物件,呼叫其實是proxy.aa()方法時,將引數和目標函式code寫進Binder驅動中,並通過回撥服務端Stub.onTransact()方法,實現呼叫真正的Stub.aa()方法
https://www.cnblogs.com/huangjialin/p/7738104.html

AIDL和Messenger的區別

Messenger不適用大量併發的請求:Messenger以序列的方式來處理客戶端發來的訊息,如果大量的訊息同時傳送到服務端,服務端仍然只能一個個的去處理。
Messenger主要是為了傳遞訊息:對於需要跨程式呼叫服務端的方法,這種情景不適用Messenger。
Messenger的底層實現是AIDL,系統為我們做了封裝從而方便上層的呼叫。
AIDL適用於大量併發的請求,以及涉及到服務端端方法呼叫的情況

binder通訊機制,binder如何被不同app程式使用的,binder如何啟動?

zygote的runOnce()-zygoteInit()-nativeZygoteInit(),

再看看ProcessState::startThreadPool()函式,看看它是怎麼啟動執行緒池的

怎麼啟用binder機制

開啟binder驅動

對映記憶體,分配緩衝區

註冊binder執行緒

進入binder loop,不斷的和binder驅動互動

問題:應用是怎麼啟用binder機制的?

1,什麼時候啟用binder機制,啟用時機是什麼,

說下AP啟動流程

2,怎麼啟用binder機制,就是上面列出的4條

淺析邏輯地址與實體地址對映關係

https://blog.csdn.net/teemo_king/article/details/79133401

相關文章