Android 核心分析 之六 -----IPC框架分析 Binder,Service,Se...

我首先從宏觀的角度觀察 Binder,Service,Service Manager,並闡述 各自的概念。從 Linux 的概念空間中, Android 的設計 Activity託管在不一樣的 的進程, Service 也都是託管在不一樣的進程,不一樣進程間的 Activity,Service 之間要交換數據屬於 IPC Binder 就是爲了 Activity通信而設計的一個輕量級的 IPC 框架。

在代碼分析中,我發現Android中只是把Binder理解成進程間通信的實現,有點狹隘,而是應該站在公共對象請求代理這個高度來理解BinderService的概念,這樣咱們就會看到不同的格局,從這個高度來理解設計意圖,咱們纔會對Android中的一些天才想法感到驚奇。從Android的外特性概念空間中,咱們看不到進程的概念,而是ActivityServiceAIDLINTENT。通常的若是我做爲設計者,在咱們的根深蒂固的想法中,這些都是以下的C/S架構,客戶端和服務端直接經過Binder交互數據,打開Binder寫入數據,經過Binder讀取數據,通信就能夠完成了。 java


 

該注意到Android的概念中,Binder是一個很低層的概念,上面一層根本都看不到Binder,而是Activity跟一個Service的對象直接經過方法調用,獲取服務。 android

 

這個就是Android提供給咱們的外特性:在Android中,要完成某個操做,所須要作的就是請求某個有能力的服務對象去完成動做,而無需知道這個通信是怎樣工做的,以及服務在哪裏。因此AndoidIPC在本質上屬於對象請求代理架構,Android的設計者用CORBA的概念將本身包裝了一下,實現了一個微型的輕量級CORBA架構,這就是AndoidIPC設計的意圖所在,它並非僅僅解決通信,而是給出了一個架構,一種設計理念,這就是Android的閃光的地方。AndroidBinder更多考慮了數據交換的便捷,而且只是解決本機的進程間的通信,因此不像CORBA那樣複雜,因此叫作輕量級。 c++

因此要理解AndroidIPC架構,就須要瞭解CORBA的架構。而CORBA的架構在本質上能夠使用下面圖來表示: 架構

 




 

在服務端,多了一個代理器,更爲抽象一點咱們能夠下圖來表示。 框架

 


 


 

分析和CORBA的大致理論架構,我給出下面的Android的對象代理結構。 函數


 



 

在結構圖中,咱們能夠較爲清楚的把握Android的IPC包含了以下的概念: spa

 

  • 設備上下文什(ContextObject

    設備上下文包含關於客服端,環境或者請求中沒有做爲參數傳遞個操做的上下文信息,應用程序開發者用ContextObject接口上定義的操做來建立和操做上下文。 設計

  •  Android代理:這個是指代理對象
  •  Binder Linux內核提供的Binder通信機制

 

Android的外特性空間是不須要知道服務在那裏,只要經過代理對象完成請求,可是咱們要探究Android是如何實現這個架構,首先要問的是在Client端要完成雲服務端的通信,首先應該知道服務在哪裏?咱們首先來看看Service Manger管理了那些數據。Service Manager提供了add service,check service兩個重要的方法,而且維護了一個服務列表記錄登記的服務名稱和句柄。 代理



 

 

 

 

 

 

 


 

Service manager service使用0來標識本身。而且在初始化的時候,經過binder設備使用BINDER_SET_CONTEXT_MGR ioctl將本身變成了CONTEXT_MGR。Svclist中存儲了服務的名字和Handle,這個Handle做爲Client端發起請求時的目標地址。服務經過add_service方法將本身的名字和Binder標識handle登記在svclist中。而服務請求者,經過check_service方法,經過服務名字在service list中獲取到service 相關聯的Binder的標識handle,經過這個Handle做爲請求包的目標地址發起請求。 對象

 

 

 

 

 

咱們理解了Service Manager的工做就是登記功能,如今再回到IPC上,客服端如何創建鏈接的?咱們首先回到通信的本質:IPC。從通常的概念來說,Android設計者在Linux內核中設計了一個叫作Binder的設備文件,專門用來進行Android的數據交換。全部從數據流來看Java對象從JavaVM空間進入到C++空間進行了一次轉換,並利用C++空間的函數將轉換過的對象經過driver/binder設備傳遞到服務進程,從而完成進程間的IPC。這個過程能夠用下圖來表示。

 

 


 

 


 

這裏數據流有幾層轉換過程。

(1) 從JVM空間傳到c++空間,這個是靠JNI使用ENV來完成對象的映射過程。

(2) 從c++空間傳入內核Binder設備,使用ProcessState類完成工做。

(3) Service從內核中Binder設備讀取數據。

Android設計者須要利用面嚮對象的技術設計一個框架來屏蔽掉這個過程。要讓上層概念空間中沒有這些細節。Android設計者是怎樣作的呢?咱們經過c++空間代碼分析,看到有以下空間概念包裝(ProcessState@(ProcessState.cpp)



       在ProcessState類中包含了通信細節,利用open_binder打開Linux設備dev/binder,經過ioctrl創建的基本的通信 框架。利用上層傳遞下來的servicehandle來肯定請求發送到那個Service。經過分析我終於明白了BnbinderBpBinder的命名含義,Bn-表明Native,而Bp表明Proxy。一旦理解到這個層次,ProcessState就容易弄明白了。

 

     下面咱們看JVM概念空間中對這些概念的包裝。爲了通篇理解設備上下文,咱們須要將Android VM概念空間中的設備上下文和C++空間總的設備上下文鏈接起來進行研究。

爲了在上層使用統一的接口,在JVM層面有兩個東西。在Android中,爲了簡化管理框架,引入了ServiceManger這個服務。全部的服務都是從ServiceManager開始的,只用經過Service Manager獲取到某個特定的服務標識構建代理IBinder。在Android的設計中利用Service Manager是默認的Handle0,只要設置請求包的目標句柄爲0,就是發給Service Manager這個Service的。在作服務請求時,Android創建一個新的Service Manager ProxyService Manager Proxy使用ContexObject做爲BinderService Manager Service(服務端)進行通信。

 

咱們看到Android代碼通常的獲取Service創建本地代理的用法以下:

IXXX  mIxxx=IXXXInterface.Stub.asInterface(ServiceManager.getService("xxx"));

 

例如:使用輸入法服務:

IInputMethodManager mImm=

IInputMethodManager.Stub.asInterface(ServiceManager.getService("input_method"));

 


這些服務代理獲取過程分解以下:

 

(1) 經過調用GetContextObject調用獲取設備上下對象。注意在AndroidJVM概念空間的ContextObject只是 Service Manger Service通信的代理Binder有對應關係。這個跟c++概念空間的GetContextObject意義是不同的。

注意看看關鍵的代碼

 

    BinderInternal.getContextObject()    @BinderInteral.java

    NATIVE JNI:getContextObject()   @android_util_Binder.cpp

Android_util_getConextObject            @android_util_Binder.cpp

     ProcessState::self()->getCotextObject(0)  @processState.cpp

      getStrongProxyForHandle(0)  @

         NEW BpBinder(0)

 

注意ProcessState::self()->getCotextObject(0) @processtate.cpp,就是該函數在進程空間創建 ProcessState對象,打開了Binder設備dev/binder,而且傳遞了參數0,這個0表明了與Service Manager這個服務綁定。

(2) 經過調用ServiceManager.asInterfaceContextObject)創建一個代理ServiceManger

     mRemote= ContextObject(Binder)

    這樣就創建起來ServiceManagerProxy通信框架。

 (3)客戶端經過調用ServiceManagergetService的方法創建一個相關的代理Binder

 

              ServiceMangerProxy.remote.transact(GET_SERVICE)

                   IBinder=ret.ReadStrongBinder() -》這個就是JVM空間的代理Binder

                      JNI Navite: android_os_Parcel_readStrongBinder()    @android_util_binder.cpp

                            Parcel->readStrongBinder()  @pacel.cpp

                                      unflatten_binder  @pacel.cpp

                                                getStrongProxyForHandle(flat_handle)

                                                          NEW BpBinder(flat_handle)-》這個就是底層c++空間新建的代理Binder。

整個創建過程能夠使用以下的示意圖來表示:

 

 


 

 



      Activity爲了創建一個IPC,須要創建兩個鏈接:訪問Servicemanager Service的鏈接,IXXX具體XXX Service的代理對象與XXXService的鏈接。這兩個鏈接對應c++空間ProcessState中BpBinder。對IXXX的操做最後就 是對BpBinder的操做。因爲咱們在寫一個Service時,在一個Package中寫了Service Native部分和Service Proxy部分,而Native和Proxy都實現相同的接口:IXXX Interface,可是一個在服務端,一個在客服端。客戶端調用的方式是使用remote->transact方法向Service發出請求,而 在服務端的OnTransact中則是處理這些請求。因此在Android Client空間就看到這個效果:只須要調用代理對象方法就達到了對遠程服務的調用目的,實際上這個調用路徑好長好長。

 

        咱們其實還一部分沒有研究,就是同一個進程之間的對象傳遞與遠程傳遞是區別的。同一個進程間專遞服務地和對象,就沒有代理BpBinder產生,而只是對象的直接應用了。應用程序並不知道數據是在同一進程間傳遞仍是不一樣進程間傳遞,這個只有內核中的Binder知道,因此內核Binder驅動能夠將Binder對象數據類型從BINDER_TYPE_BINDER修改成BINDER_TYPE_HANDLE或者BINDER_TYPE_WEAK_HANDLE做爲引用傳遞。

相關文章
相關標籤/搜索