IPC、Binder、AIDL與Intent之間區別與聯繫

    很多文章提到的的IPC、Binder、AIDL都是混在一起說,有時候好像覺得它們是一樣的,但是又有區別,那倒底有什麼共同點與不同呢,還有Intent與它們有什麼關係呢? 
    首先看看各自的全稱與中文名: 
    IPC:Inter-Process Communication(進程間通信) 
    Binder:Binder進程間通信機制 
    AIDL:Android Interface Definition Language(android接口定義語言) 
    Intent:意圖 
    
    再來看一張圖:  
 
    圖中最裏層是Android系統匿名共享內存Ashmem(Anonymous Shared Memory),其作用之一即通過Binder進程間通信機制來實現進程間的內存共享。 

    通過圖片與其名稱,其實已經能知道個大概: 
IPC是一種概念,即進程間通信;其它幾個都是Android裏的概念;Binder是對IPC的具體實行,是IPC的一種具體實現;AIDL是Binder機制向外提供的接口,目的就是爲了方便對Binder的使用;Intent是最高層級的封裝,實質是封裝了對Binder的使用,當然Intent也常常在同一進程中調用,只是把兩種方式封裝在一起了。 

    爲什麼搞這麼複雜呢,目的還是爲了最大發揮系統效率與方便開發者使用。 
    IPC是操作系統層面的概念,因爲進程是操作系統裏最基本的單位,進程的一大特徵就是有自己獨立的內存地址空間,所以同一進程裏的代碼能直接訪問其地址空間的內存,而其它進程是不能直接訪問的。操作系統是多進程的,多個進程配合工作肯定會涉及到互相的通信,故出現了IPC,而對IPC的實現也不是一種,有很多,且有各自的長處,比如Socket就是一種IPC,其長處就是能跨機器進行進程間通信。 
     Android系統的本質上其實是Linux系統,可以看成是在Linux內核上運行着一個超級程序。雖然Linux本身提供了很多IPC機制,但是Android主要是運行在手機上了,爲了能更好的適應手機這個環境同時簡化開發,Binder機制出現了,而Binder本質上是通過共享內存來實現的IPC( 直白點就是一段物理內存在不同進程中都映射了虛擬地址(虛擬地址可能不同),一個對它寫,另一個對它讀,然後解析、處理),但是Binder機制不是簡簡單單共享內存,而是搭了一套巧妙的架構,來達到最終共享內存進行IPC的目的。 

     Binder     
      Binder機制具體的實現涉及到很多C/C++的代碼,我們瞭解一下其思想就行了: 
Binder通信採用的是client-server通信結構,client與server的通信由Binder驅動程序和Service Manager組件協助,這兩個組件Android已經實現好了並由系統運行,而開發者只需要按照框架規範實現client與server接口即可。參考下圖: 
 

   具體的通信過程如下圖: 
 
   什麼意思呢: 
   1.client通過獲得一個server的代理接口,對server進行直接調用 
   2.實際上代理接口中定義的方法與server中定義的方法是一一對應的 
   3.client調用某個代理接口中的方法時,代理接口的方法會將client傳遞的參數打包成爲Parcel對象 
   4.代理接口將該Parcel發送給內核中的binder driver. 
   5.server會讀取binder driver中的請求數據,如果是發送給自己的,解包Parcel對象,處理並將結果返回 
   6.整個的調用過程是一個同步過程,在server處理的時候,client會block住 
    
       AIDL    
       AIDL是爲了方便使用Binder框架搞的一個東東,其實不用這個也能達到目的,但是用這個就簡化了操作。 
       只要按照規範寫一個.aidl文件,插件會幫助自動創建一個與interface同名的.java文件,裏面已經幫我們自動寫好一堆東東,這些標準化的東西,用模板自動生成即可,讓開發者儘量關注功能實現上。 
       .aidl的寫法非常簡單,與java接口的定義很類似: 
       比如: 
Java代碼  收藏代碼
  1.      
  2. interface MyAidl{    
  3.     int getId();  
  4.       
  5.     void setId(int id);  
  6.   }  

       自動生成的.java中有一個重要的內部類Stub,其繼承了Binder類,需要實現我們定義的interface 
      比如: 
Java代碼  收藏代碼
  1. public static abstract class Stub extends android.os.Binder implements com.xxx.MyAidl {  
  2.      public static com.xxx.MyAidl asInterface(android.os.IBinder obj);  
  3.      public boolean onTransact(int code, android.os.Parcel data,android.os.Parcel reply, int flags);  
  4.   
  5.      private static class Proxy implements com.hsae.recorder.encoder.Mp4EncoderAidl {  
  6.             ......  
  7.       }  
  8.   }  

      Binder類既作爲服務器端接口也作爲Binder驅動,客戶端接口會獲得Binder驅動,調用其transact()發送消息至服務器,而服務器端接口會接收Binder驅動發送的消息,收到消息後,會執行Binder對象中的onTransact()函數,並按照該函數的參數執行不同的服務器端代碼。 
      Proxy實例中會傳入Binder驅動,並且封裝了調用服務端的代碼,客戶端會通過Binder驅動的transact()方法調用服務端代碼。 
      最後分析得出,客戶端中獲取的就是Proxy實例。 

      Intent 
      Intent進行進程間通信比較常見,比如打開另一個應用的Activity、發送廣播等。Intent的架構包括三方面: 
      Client,發送這個Intent的activity; 
      Server,activityManagerService.java,它主要是負責分發這些Intent給適當的對象; 
      Target,也就是那些需要處理這個Intent的activity,稱爲Receiver; 
    
      而進程間發送消息或者broadcast,並不是直接把intent發過去,而是把intent打包到Parcel中,通過binder機制傳遞消息。 
      
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章