Android 核心分析 之六 —–IPC架構分析 Binder,Service,Service manager

來源:互聯網
上載者:User
from :http://blog.csdn.net/maxleng/article/details/5490770

 

IPC架構分析 Binder,Service,Service manager

 

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

在程式碼分析中,我發現Android中只是把Binder理解成進程間通訊的實現,有點狹隘,而是應該站在公用對象請求代理這個高度來理解Binder,Service的概念,這樣我們就會看到不一樣的格局,從這個高度來理解設計意圖,我們才會對Android中的一些天才想法感到驚奇。從Android的外特性概念空間中,我們看不到進程的概念,而是Activity,Service,AIDL,INTENT。一般的如果我作為設計者,在我們的根深蒂固的想法中,這些都是如下的C/S架構,用戶端和服務端直接通過Binder互動資料,開啟Binder寫入資料,通過Binder讀取資料,通訊就可以完成了。

 

 

 

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

 

這個就是Android提供給我們的外特性:在Android中,要完成某個操作,所需要做的就是請求某個有能力的服務物件去完成動作,而無需知道這個通訊是怎樣工作的,以及服務在哪裡。所以Andoid的IPC在本質上屬於對象請求代理架構,Android的設計者用CORBA的概念將自己封裝了一下,實現了一個微型的輕量級CORBA架構,這就是Andoid的IPC設計的意圖所在,它並不是僅僅解決通訊,而是給出了一個架構,一種設計理念,這就是Android的閃光的地方。Android的Binder更多考慮了資料交換的便捷,並且只是解決原生進程間的通訊,所以不像CORBA那樣複雜,所以叫做輕量級。

所以要理解Android的IPC架構,就需要瞭解CORBA的架構。而CORBA的架構在本質上可以使用下面圖來表示:

 

 

 

 

 

 

在服務端,多了一個代理器,更為抽象一點我們可以來表示。

 

 

 

 

 

 

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

 

 

 

 

 

 

在結構圖中,我們可以較為清楚的把握Android的IPC包含了如下的概念:

 

  • 裝置上下文什(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對象從Java的VM空間進入到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。通過分析我終於明白了Bnbinder,BpBinder的命名含義,Bn-代表Native,而Bp代表Proxy。一旦理解到這個層次,ProcessState就容易弄明白了。

 

 

     下面我們看JVM概念空間中對這些概念的封裝。為了通篇理解裝置上下文,我們需要將Android VM概念空間中的裝置上下文和C++空間總的裝置上下文串連起來進行研究。

為了在上層使用統一的介面,在JVM層面有兩個東西。在Android中,為了簡化管理架構,引入了ServiceManger這個服務。所有的服務都是從ServiceManager開始的,只用通過Service Manager擷取到某個特定的服務識別構建代理IBinder。在Android的設計中利用Service Manager是預設的Handle為0,只要佈建要求包的目標控制代碼為0,就是發給Service Manager這個Service的。在做服務要求時,Android建立一個新的Service Manager Proxy。Service Manager Proxy使用ContexObject作為Binder和Service Manager Service(服務端)進行通訊。

 

我們看到Android代碼一般的擷取Service建立本地代理的用法如下:

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

 

例如:使用IME服務:

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.asInterface(ContextObject)建立一個代理ServiceManger。

     mRemote= ContextObject(Binder)

    這樣就建立起來ServiceManagerProxy通訊架構。

 (3)用戶端通過調用ServiceManager的getService的方法建立一個相關的代理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作為引用傳遞。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.