Binder 通訊採用 C/S 架構,從組件視角來講,包含 Client、 Server、 ServiceManager 以及 Binder 驅動,其中 ServiceManager 用於管理系統中的各類服務。程序員
Binder 在 framework 層進行了封裝,經過 JNI 技術調用 Native(C/C++)層的 Binder 架構。 緩存
Binder 在 Native 層以 ioctl 的方式與 Binder 驅動通信。架構
首先須要註冊服務端,只有註冊了服務端,客戶端纔有通信的目標,服務端經過 ServiceManager 註冊服務,註冊的過程就是向 Binder 驅動的全局鏈表 binder_procs 中插入服務端的信息(binder_proc 結構體,每一個 binder_proc 結構體中都有 todo 任務隊列),而後向 ServiceManager 的 svcinfo 列表中緩存一下注冊的服務。 併發
有了服務端,客戶端就能夠跟服務端通信了,通信以前須要先獲取到服務,拿到服務的代理,也能夠理解爲引用。 獲取服務端的方式就是經過 ServiceManager 向 svcinfo 列表中查詢一下返回服務端的代理,svcinfo 列表就是全部已註冊服務的通信錄,保存了全部註冊的服務信息。 app
有了服務端的引用咱們就能夠向服務端發送請求了,經過 BinderProxy 將咱們的請求參數發送給 ServiceManager,經過共享內存的方式使用內核方法 copy_from_user() 將咱們的參數先拷貝到內核空間,這時咱們的客戶端進入等待狀態,而後 Binder 驅動向服務端的 todo 隊列裏面插入一條事務,執行完以後把執行結果經過 copy_to_user() 將內核的結果拷貝到用戶空間(這裏只是執行了拷貝命令,並無拷貝數據,binder只進行一次拷貝),喚醒等待的客戶端並把結果響應回來,這樣就完成了一次通信 。異步
Binder 線程池:不管是system_server進程,仍是app進程,都是在進程fork完成後,便會在新進程中執行onZygoteInit()的過程當中,啓動binder線程池。每一個 Server 進程在啓動時建立一個 binder 線程池,並向其中註冊一個 Binder 線程;以後 Server 進程也能夠向 binder 線程池註冊新的線程,或者 Binder 驅動在探測到沒有空閒 binder 線程時主動向 Server 進程註冊新的的 binder 線程。對於一個 Server 進程有一個最大 Binder 線程數限制,默認爲16個 binder 線程,例如 Android 的 system_server 進程就存在16個線程。對於全部 Client 端進程的 binder 請求都是交由 Server 端進程的 binder 線程來處理的。 ide
對於底層Binder驅動,經過 binder_procs 鏈表記錄全部建立的 binder_proc 結構體,binder 驅動層的每個 binder_proc 結構體都與用戶空間的一個用於 binder 通訊的進程一一對應,且每一個進程有且只有一個 ProcessState 對象,這是經過單例模式來保證的。在每一個進程中能夠有不少個線程,每一個線程對應一個 IPCThreadState 對象,IPCThreadState 對象也是單例模式,即一個線程對應一個 IPCThreadState 對象,在 Binder 驅動層也有與之相對應的結構,那就是 Binder_thread 結構體。在 binder_proc 結構體中經過成員變量 rb_root threads,來記錄當前進程內全部的 binder_thread。 函數
https://blog.csdn.net/freekiteyu/article/details/70082302
oop
Binder線程是執行Binder服務的載體,只對於服務端纔有意義,對請求端來講,是不須要考慮Binder線程的,但Android系統的處理機制其實大部分是互爲C/S的。好比APP與AMS進行交互的時候,都互爲對方的C與S,這裏先不討論這個問題,先看Binder線程的概念。性能
Binder線程就是執行Binder實體業務的線程,一個普通線程如何才能成爲Binder線程呢?很簡單,只要開啓一個監聽Binder字符設備的Loop線程便可,在Android中有不少種方法,不過歸根到底都是監聽Binder,換成代碼就是經過ioctl來進行監聽。
拿ServerManager進程來講,其主線就是Binder線程,其作法是經過binder_loop實現不死線程。咱們APP的主線程,在startActivity請求AMS的時候,APP的主線程成其實就是Binder請求線程,在進行Binder通訊的過程當中,Client的Binder請求線程會一直阻塞,直到Service處理完畢返回處理結果。
雖然APP開發時候,Binder對程序員幾乎不可見,可是做爲Android的數據運輸系統,Binder的影響是全面性的,因此有時候若是不瞭解Binder的一些限制,在出現問題的時候每每是沒有任何頭緒,好比在Activity之間傳輸BitMap的時候,若是Bitmap過大,就會引發問題,好比崩潰等,這其實就跟Binder傳輸數據大小的限制有關係,在上面的一次拷貝中分析過,mmap函數會爲Binder數據傳遞映射一塊連續的虛擬地址,這塊虛擬內存空間實際上是有大小限制的,不一樣的進程可能還不同。普通的由Zygote孵化而來的用戶進程,所映射的Binder內存大小是不到1M的,這個限制定義在ProcessState類中,若是傳輸說句超過這個大小,系統就會報錯,由於Binder自己就是爲了進程間頻繁而靈活的通訊所設計的,並非爲了拷貝大數據而使用的。
服務可分爲系統服務與普通服務,系統服務通常是在系統啓動的時候,由SystemServer進程建立並註冊到ServiceManager中的。而普通服務通常是經過ActivityManagerService啓動的服務,或者說經過四大組件中的Service組件啓動的服務。這兩種服務在實現跟使用上是有不一樣的,主要從如下幾個方面:
首先看一下服務的啓動上,系統服務通常都是SystemServer進程負責啓動,好比AMS,WMS,PKMS,電源管理等,這些服務自己其實實現了Binder接口,做爲Binder實體註冊到ServiceManager中,被ServiceManager管理,而SystemServer進程裏面會啓動一些Binder線程,主要用於監聽Client的請求,並分發給響應的服務實體類,能夠看出,這些系統服務是位於SystemServer進程中(有例外,好比Media服務)。在來看一下bindService類型的服務,這類服務通常是經過Activity的startService或者其餘context的startService啓動的,這裏的Service組件只是個封裝,主要的是裏面Binder服務實體類,這個啓動過程不是ServcieManager管理的,而是經過ActivityManagerService進行管理的,同Activity管理相似。
再來看一下服務的註冊與管理:系統服務通常都是經過ServiceManager的addService進行註冊的,這些服務通常都是須要擁有特定的權限才能註冊到ServiceManager,而bindService啓動的服務能夠算是註冊到ActivityManagerService,只不過ActivityManagerService管理服務的方式同ServiceManager不同,而是採用了Activity的管理模型,詳細的能夠自行分析
最後看一下使用方式,使用系統服務通常都是經過ServiceManager的getService獲得服務的句柄,這個過程其實就是去ServiceManager中查詢註冊系統服務。而bindService啓動的服務,主要是去ActivityManagerService中去查找相應的Service組件,最終會將Service內部Binder的句柄傳給Client。