<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ### 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讀取數據,通訊就可以完成了。 ![](https://box.kancloud.cn/2016-05-05_572b1a162ec7b.gif) 該注意到Android的概念中,Binder是一個很低層的概念,上面一層根本都看不到Binder,而是Activity跟一個Service的對象直接通過方法調用,獲取服務。 這個就是Android提供給我們的外特性:在Android中,要完成某個操作,所需要做的就是請求某個有能力的服務對象去完成動作,而無需知道這個通訊是怎樣工作的,以及服務在哪里。所以Andoid的IPC在本質上屬于對象請求代理架構,Android的設計者用CORBA的概念將自己包裝了一下,實現了一個微型的輕量級CORBA架構,這就是Andoid的IPC設計的意圖所在,它并不是僅僅解決通訊,而是給出了一個架構,一種設計理念,這就是Android的閃光的地方。Android的Binder更多考慮了數據交換的便捷,并且只是解決本機的進程間的通訊,所以不像CORBA那樣復雜,所以叫做輕量級。 所以要理解Android的IPC架構,就需要了解CORBA的架構。而CORBA的架構在本質上可以使用下面圖來表示: ![](https://box.kancloud.cn/2016-05-05_572b1a163e071.gif) 在服務端,多了一個代理器,更為抽象一點我們可以下圖來表示。 ![](https://box.kancloud.cn/2016-05-05_572b1a16505cf.gif) 分析和CORBA的大體理論架構,我給出下面的Android的對象代理結構。 ![](https://box.kancloud.cn/2016-05-05_572b1a16654ca.gif) 在結構圖中,我們可以較為清楚的把握Android的IPC包含了如下的概念: - 設備上下文什(ContextObject) 設備上下文包含關于客服端,環境或者請求中沒有作為參數傳遞個操作的上下文信息,應用程序開發者用ContextObject接口上定義的操作來創建和操作上下文。 - ?Android代理:這個是指代理對象 - ?Binder?Linux內核提供的Binder通訊機制 Android的外特性空間是不需要知道服務在那里,只要通過代理對象完成請求,但是我們要探究Android是如何實現這個架構,首先要問的是在Client端要完成云服務端的通訊,首先應該知道服務在哪里?我們首先來看看Service?Manger管理了那些數據。Service?Manager提供了add?service,check?service兩個重要的方法,并且維護了一個服務列表記錄登記的服務名稱和句柄。 ![](https://box.kancloud.cn/2016-05-05_572b1a167a4cc.gif) 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。這個過程可以用下圖來表示。 ![](https://box.kancloud.cn/2016-05-05_572b1a168b6b3.gif) 這里數據流有幾層轉換過程。 (1)?從JVM空間傳到c++空間,這個是靠JNI使用ENV來完成對象的映射過程。 (2)?從c++空間傳入內核Binder設備,使用ProcessState類完成工作。 (3)?Service從內核中Binder設備讀取數據。 Android設計者需要利用面向對象的技術設計一個框架來屏蔽掉這個過程。要讓上層概念空間中沒有這些細節。Android設計者是怎樣做的呢?我們通過c++空間代碼分析,看到有如下空間概念包裝(ProcessState@(ProcessState.cpp) ![](https://box.kancloud.cn/2016-05-05_572b1a169f3fa.gif) 在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")); 例如:使用輸入法服務: 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。 整個建立過程可以使用如下的示意圖來表示: ![](https://box.kancloud.cn/2016-05-05_572b1a16bb27f.gif) 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作為引用傳遞。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看