Binder總結篇1-Binder原理

Binder總結篇1-Binder原理

須要學會Binder的基本使用和原理,須要的知識點有:java

  1. Linux進程和空間的概念android

  2. 虛擬地址概念git

  3. 經常使用IPC,他們的基本流程和Binder的區別緩存

  4. C/S架構基本思路,也就是Binder驅動,ServerManager,Client和Server這四個概念。安全

  5. AIDL以及支持的數據類型,包括Parcelable等,以及編寫服務器

  6. Service(Android的四大組件之一),Binder等幾個具體的java類使用。網絡

如下是本身的一些Binder學習總結,若有侵權請聯繫刪除。架構

Linux的進程和空間的概念

在Linux系統中,進程是分配給應用程序運行的最小描述,即一個應用程序最少有一個進程,而一個進程之間又最少有一個線程,進程給應用程序分配內存空間。ide

空間:在Linux中,爲了保持系統的穩定性,分爲內核空間和用戶空間,內核空間的權限最高,用戶空間的權限最低。好比讀寫文件,網絡請求就是在內核空間中進行的。學習

在Linux中,存在着進程隔離,也就是進程A沒法直接訪問進程B的數據,他們之間各自具備獨立的內存。假如他們須要進行通訊,就必須經過IPC來實現,主要是經過兩個方法:copy_from_usercopy_to_user

虛擬地址

在給應用程序分配內存的時候,對於應用程序來講,他是一片連續的內存空間,可是實際上,這些內存空間映射到具體的物理內存中是碎片化的不連續的,這個在應用程序看來是連續的空間就是經過虛擬地址實現的。經過虛擬地址,讓應用程序看似擁有連續的內存空間,從而映射到具體的物理內存中。

好比,在32位系統中,能夠尋址的空間長度是2的32次方,也就是4GB。

傳統IPC

包括:

  1. 共享內存

  2. 消息管道

  3. Socket

  4. 信號量

這些是經常使用的IPC方法,通常而言,他們會經歷兩次的數據copy,共享內存除外。

第一次是發送方將數據經過copy_from_user拷貝到內核空間中,這是第一次。而後,接收方在本身的內存空間中,分配緩存區,經過copy_to_user方法把內核空間的數據複製到本身進行讀取。

以下圖:

對於Android系統而言,上面的幾種方式都不太適合,首先對於兩次的數據拷貝,存在的問題是:

  1. copy次數多耗費時間

  2. 接收方不知道須要分配多大的內存接受數據,或者是須要提早通知接受方分配而耗費時間。

對於共享內存,雖然它無需copy可是較爲難以控制,安全性方面較差。

那麼Binder在這方面具備什麼優點呢?

  1. Binder是隻須要一次數據copy,僅低於共享內存。

  2. 他基於C/S架構,職責分離又相互獨立,穩定性更好。

  3. 在安全性方面,傳統的IPC接收方沒法獲取對方可靠的進程PId,從而沒法鑑別對方身份。可是在Android中,他會爲每個安裝好的App分配一個本身的UID,從而作到能夠鑑別身份。

因此Binder是Android系統進行IPC採用的手段。那麼Binder爲何只是能夠一次數據拷貝就好了呢?

這個就是利用虛擬內存了。Binder藉助內存映射,在內核空間和接收方的用戶空間的數據緩存區作了一層內存映射。也就是說,在發送方將數據拷貝到內存空間的時候,內核空間的這部分地址同時也會被映射到接收方的內存緩存中,這樣子,就少了一次從內和空間拷貝到用戶空間。

以下圖:

Binder 的通訊原理

在Binder中,有四個概念,Binder驅動,ServerManager,Client以及Server,這四個部分組成了BinderC/S架構。

他跟一次網絡請求很類似:Client經過域名發起請求,經過DNS域名解析器解析具體的ip地址,而後再經過路由轉發到具體的Server,再而後Server將請求結果經過路由轉發回Client。

在Binder的IPC中,有以下幾個部分:

  1. Binder驅動

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能夠找到。

  1. Client

Client的做用是發起請求,經過Binder向ServerManager發起請求獲取Server的具體地址,而後交由Binder驅動轉發。

  1. Server

Server假如須要對外提供服務,他就須要先將本身註冊到ServerManager中,以便被解析出來。Server在響應請求以後,就將數據經過Binder驅動再次將數據傳遞會Client。

這就是一次完整的IPC調用。

還有一個問題就是ServerManager的產生,由於Client/Server都是須要經過Binder與ServerManager進行通訊的,那麼這個ServerManager是如何產生的呢?

  1. 在Android系統啓動以後,會建立一個名詞爲servermanager的進程,能夠查看ZygoteInit文件,在裏面的main方法中,調用ZygoteforkSystemServer產生。它經過一個約定的命令BINDERSERVER_MGR向Binder驅動註冊,申請成爲ServerManager。Binder驅動會自動爲ServerManager建立一個Binder實體

  2. 這個Binder實體的引用在全部的Client中都是0,也就是說各個Client經過0這個引用就能夠與ServerManager進行通訊。

Binder的代理機制

上面是咱們的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。

以下圖

AIDL

上面咱們大概梳理了Binder調用的總體流程,知道Binder的大概原理。在Android中,是經過AIDL這一描述性接口語言實現的。

什麼是AIDL:Android 接口定義語言 (AIDL)

關於如何使用AIDL將在下一篇文章在作詳細使用。

參考文章

關於Binder,做爲應用開發者你須要知道的所有(同時也是本文的文章圖片來源)

爲何Android要採用Binder做爲IPC機制

Binder系列-開篇

Android 跨進程通訊:圖文詳解Binder機制原理

寫給 Android 應用工程師的 Binder 原理剖析

相關文章
相關標籤/搜索