須要學會Binder的基本使用和原理,須要的知識點有:java
Linux進程和空間的概念android
虛擬地址概念git
經常使用IPC,他們的基本流程和Binder的區別緩存
C/S架構基本思路,也就是Binder驅動,ServerManager,Client和Server這四個概念。安全
AIDL以及支持的數據類型,包括Parcelable等,以及編寫服務器
Service(Android的四大組件之一),Binder等幾個具體的java類使用。網絡
如下是本身的一些Binder學習總結,若有侵權請聯繫刪除。架構
在Linux系統中,進程是分配給應用程序運行的最小描述,即一個應用程序最少有一個進程,而一個進程之間又最少有一個線程,進程給應用程序分配內存空間。ide
空間:在Linux中,爲了保持系統的穩定性,分爲內核空間和用戶空間,內核空間的權限最高,用戶空間的權限最低。好比讀寫文件,網絡請求就是在內核空間中進行的。學習
在Linux中,存在着進程隔離,也就是進程A沒法直接訪問進程B的數據,他們之間各自具備獨立的內存。假如他們須要進行通訊,就必須經過IPC來實現,主要是經過兩個方法:copy_from_user
和copy_to_user
。
在給應用程序分配內存的時候,對於應用程序來講,他是一片連續的內存空間,可是實際上,這些內存空間映射到具體的物理內存中是碎片化的不連續的,這個在應用程序看來是連續的空間就是經過虛擬地址實現的。經過虛擬地址,讓應用程序看似擁有連續的內存空間,從而映射到具體的物理內存中。
好比,在32位系統中,能夠尋址的空間長度是2的32次方,也就是4GB。
包括:
共享內存
消息管道
Socket
信號量
這些是經常使用的IPC方法,通常而言,他們會經歷兩次的數據copy,共享內存除外。
第一次是發送方將數據經過copy_from_user
拷貝到內核空間中,這是第一次。而後,接收方在本身的內存空間中,分配緩存區,經過copy_to_user
方法把內核空間的數據複製到本身進行讀取。
以下圖:
對於Android系統而言,上面的幾種方式都不太適合,首先對於兩次的數據拷貝,存在的問題是:
copy次數多耗費時間
接收方不知道須要分配多大的內存接受數據,或者是須要提早通知接受方分配而耗費時間。
對於共享內存,雖然它無需copy可是較爲難以控制,安全性方面較差。
那麼Binder在這方面具備什麼優點呢?
Binder是隻須要一次數據copy,僅低於共享內存。
他基於C/S架構,職責分離又相互獨立,穩定性更好。
在安全性方面,傳統的IPC接收方沒法獲取對方可靠的進程PId,從而沒法鑑別對方身份。可是在Android中,他會爲每個安裝好的App分配一個本身的UID,從而作到能夠鑑別身份。
因此Binder是Android系統進行IPC採用的手段。那麼Binder爲何只是能夠一次數據拷貝就好了呢?
這個就是利用虛擬內存了。Binder藉助內存映射,在內核空間
和接收方的用戶空間
的數據緩存區作了一層內存映射。也就是說,在發送方將數據拷貝到內存空間的時候,內核空間的這部分地址同時也會被映射到接收方的內存緩存中,這樣子,就少了一次從內和空間拷貝到用戶空間。
以下圖:
在Binder中,有四個概念,Binder驅動,ServerManager,Client以及Server,這四個部分組成了BinderC/S架構。
他跟一次網絡請求很類似:Client經過域名發起請求,經過DNS域名解析器解析具體的ip地址,而後再經過路由轉發到具體的Server,再而後Server將請求結果經過路由轉發回Client。
在Binder的IPC中,有以下幾個部分:
Binder驅動是一種虛擬的字符設備,註冊在/dev/bindr中,其中定義了一套Binder通訊協議,負責創建進程間Binder通訊,提供了數據包在進程之間傳遞的底層支持。
他的角色相似路由,他是提供進程間通訊的底層支持。負責將Client端的請求轉發到Server,並將Server的數據返回給Client。
2 ServerManager
他的做用相似DNS服務器,負責將Client請求的Server的Binder描述轉化爲具體的Server地址,以便Binder驅動將Client的請求轉達到Server。當Server須要提供服務的時候,他必須先向ServerManager註冊,這樣子,ServerManager中,就存有一份相似key-value的數據,保存了一份Server的Binder字符名稱和Binder引用的映射以便Client能夠找到。
Client的做用是發起請求,經過Binder向ServerManager發起請求獲取Server的具體地址,而後交由Binder驅動轉發。
Server假如須要對外提供服務,他就須要先將本身註冊到ServerManager中,以便被解析出來。Server在響應請求以後,就將數據經過Binder驅動再次將數據傳遞會Client。
這就是一次完整的IPC調用。
還有一個問題就是ServerManager的產生,由於Client/Server都是須要經過Binder與ServerManager進行通訊的,那麼這個ServerManager是如何產生的呢?
在Android系統啓動以後,會建立一個名詞爲servermanager的進程,能夠查看ZygoteInit
文件,在裏面的main方法中,調用Zygote
的forkSystemServer
產生。它經過一個約定的命令BINDERSERVER_MGR向Binder驅動註冊,申請成爲ServerManager。Binder驅動會自動爲ServerManager建立一個Binder實體
這個Binder實體的引用在全部的Client中都是0,也就是說各個Client經過0這個引用就能夠與ServerManager進行通訊。
上面是咱們的IPC過程,在這個過程當中,Client須要獲取到Server端的Binder引用,那麼這個引用是真正的Server引用嗎,他是如何實現的呢,A進程並沒有法直接獲取B進程的對象。這個就是須要經過Binder的代理機制實現。
咱們在Client端,向ServerManager獲取具體的Server端的Binder引用的時候,會首先進過Binder驅動,Binder驅動它並不會把真正的Server的Bind人引用返回給Client端,而是返回一個代理的java對象,該對象具備跟Server端的Binder引用相同的方法簽名,這個對象爲ProxyObject,他具備跟Server的Binder實例同樣的方法,只是這些方法並無Server端的能力,這個ProxyObject的能力是能夠經過Binder驅動,正在實現對Server的Binder進行調用,從而完成數據傳遞。
好比,當Binder驅動接受到Client進程的請求,就去ServerManager中查詢,在ServerManager中查詢到具體的Server具體以後,就建立一個Server端的Binder對象的ProxyObject,而且將該ProxyObject返回給Client 。而後Client就經過ProxyObject調用其中的方法,ProxyObject的方法再去調用Binder驅動,這個Binder驅動就去Server進程中,調用具體的Server進程的具體的Binder對象的方法,而後再經過Binder驅動返回數據給Client。
以下圖
上面咱們大概梳理了Binder調用的總體流程,知道Binder的大概原理。在Android中,是經過AIDL這一描述性接口語言實現的。
什麼是AIDL:Android 接口定義語言 (AIDL)
關於如何使用AIDL將在下一篇文章在作詳細使用。
關於Binder,做爲應用開發者你須要知道的所有(同時也是本文的文章圖片來源)