Android 之 Binder與程式間通訊

yangxi_001發表於2013-11-15

Binder機制是android中實現的程式間通訊的架構,它採用的是c/s架構,client通過代理完成對server的呼叫。

ServiceManager

既然這裡提到了server,那麼我們有必要先了解下在android中是怎麼來管理server的。先來看一個重要的Native程式:ServiceManager,從名字可以看出來,這個是用來管理所有server的。在init程式啟動之後,會啟動另外兩個重要的程式,一個是我們上一篇講的Zygote程式,另外一個就是這個ServiceManager程式了,這兩個程式啟動之後就建立了android的執行環境和server的管理環境。ServiceManager程式啟動之後其他server就可以通過ServiceManager的add_service和check_service來新增和獲取特定的server了。關於ServiceManager在接下來會詳細介紹,因為Binder會涉及到ServiceManager,所以先簡單介紹下,有個大概印象,知道他是幹什麼的就行了。

Binder與程式間通訊

在本篇介紹中,我們所指的客戶端沒有特別說明的話就指應用程式。應為service和serviceManager通訊也會涉及到IPC。

我們還是從activity的啟動開始來研究Binder的機制。來看下startActivity涉及通訊的類圖:

 

在ActivityManagerProxy中,有這句程式碼          

[java] view plaincopy
  1. IBinder b = ServiceManager.getService("activity");  
  2. 繼續看下getService方法,在getService中對資料進行了序列化封裝,並通過BinderProxy的native方法向ServiceManager傳送請求,獲取Binder的代理物件。看下getService程式碼:  

[java] view plaincopy
  1. /* 
  2.    * 從ServiceManager中獲取service對應的代理Binder 
  3.    * @param na 
  4.    * @return 
  5.    * @throws RemoteException 
  6.    */  
  7.   public IBinder getService(String name) throws RemoteException {  
  8.       Parcel data = Parcel.obtain();  
  9.       Parcel reply = Parcel.obtain();  
  10.       data.writeInterfaceToken(IServiceManager.descriptor);  
  11.       data.writeString(name);  
  12.       mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);  
  13.       IBinder binder = reply.readStrongBinder();  
  14.       reply.recycle();  
  15.       data.recycle();  
  16.       return binder;  
  17.   }  

也就是說,在android中進行IPC的話,需要先通過ServiceManager獲得客戶端的代理,然後再通過該代理與對應的service進行通訊。

  1. 建立和ServiceManager的連線,獲取客戶端物件的代理Binder。
  2. 客戶端再通過該代理binder和伺服器端進行通訊。

真正的Binder

我們在上面所提到的這些Binder實際上只是JVM中的Binder,主要作用是提供了訪問C++中的代理Binder,叫做BpBinder(BproxyBinder)。真正的Binder是Linux上的一個驅動裝置,專門用來做android的資料交換。

 

從上面分析可以看出,一次IPC通訊大概有以下三個步驟:

  1. 在JVM中對資料進行序列化,並通過BinderProxy傳遞到C++中。
  2. C++中的BpBinder對資料進行處理,並傳入到Binder裝置中(這裡是在ProcessState類中處理並呼叫BpBinder).
  3. Service從核心裝置中讀取資料。

   既然在C++中,處理資料主要是在ProcessState中,那麼我們就來看看ProcessState的程式碼,在getContextObject中呼叫了getStrongProxyForHandle方法,從而獲取了代理物件BpBinder:

[java] view plaincopy
  1. sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)  
  2. {  
  3.     sp<IBinder> result;  
  4.     AutoMutex _l(mLock);  
  5.     handle_entry* e = lookupHandleLocked(handle);  
  6.     if (e != NULL) {  
  7.         // We need to create a new BpBinder if there isn't currently one, OR we  
  8.         // are unable to acquire a weak reference on this current one.  See comment  
  9.         // in getWeakProxyForHandle() for more info about this.  
  10.         IBinder* b = e->binder;  
  11.         if (b == NULL || !e->refs->attemptIncWeak(this)) {  
  12.             b = new BpBinder(handle);  
  13.             e->binder = b;  
  14.             if (b) e->refs = b->getWeakRefs();  
  15.             result = b;  
  16.         } else {  
  17.             // This little bit of nastyness is to allow us to add a primary  
  18.             // reference to the remote proxy when this team doesn't have one  
  19.             // but another team is sending the handle to us.  
  20.             result.force_set(b);  
  21.             e->refs->decWeak(this);  
  22.         }  
  23.     }  
  24.     return result;  
  25. }  

再來看看BpBinder中的transact方法程式碼:

[java] view plaincopy
  1. status_t BpBinder::transact(  
  2.     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)  
  3. {  
  4.     // Once a binder has died, it will never come back to life.  
  5.     if (mAlive) {  
  6.         status_t status = IPCThreadState::self()->transact(  
  7.             mHandle, code, data, reply, flags);  
  8.         if (status == DEAD_OBJECT) mAlive = 0;  
  9.         return status;  
  10.     }  
  11.     return DEAD_OBJECT;  
  12. }  
在BpBinder中的transact函式中,只是呼叫了IPCThreadState::self()->transact方法,也就是說,資料處理是在IPCThreadState類中的transact。在transact中,它把請求的資料經過Binder裝置傳送給了Service。Service處理完請求後,又將結果原路返回給客戶端。

 

總結:

在android中,使用Binder進行程式間的通訊,並採用C/S架構Android中的Binder分為JVM中的、C++中的、和真正的linux中的Binder塊裝置程式間通訊首先是從JVM中對資料進行轉化並傳遞到C++中,C++中的BpBinder對資料進行處理寫入到linux中的Binder裝置,並接受Service端得請求,請求完畢後按照原路返回給呼叫端。

相關文章