(筆記)關於binder機制的一點理解

binder分爲幾個部分:client,service,serviceManager,driver,

以通過AIDL實現方式爲例,我們如果已經創建客戶端MyClient和服務端MyService,並且通過AIDL得到我們需要的引用文件(ServiceManager),這個引用文件ServiceManager.java從代碼上看是個接口,其中有個繼承Binder並實現本身接口的抽象類Stub,這個目的就是爲了讓我們在客戶端和服務端根據其不同需求實現Stub並重寫其中的方法,通過這些方法使客戶端和服務端在Binder驅動創建的共享數據緩衝區進行數據讀取。
binder運行過程
圖片來自http://blog.csdn.net/huachao1001/article/details/51504469

另外很重要的一點客戶端調用服務端或者服務端調用客戶中的一些方法(比如listener)當前線程是被掛起的,如果有耗時操作容易發生ANR,所以不要在主線程調用這些方法。

還有就是binder可能意外死亡,我們需要通過linkToDeath和unlinkToDeath設置死亡代理,去監聽並做一些處理比如重新連接
大致過程如下:
首先聲明一個DeathRecipient對象,這是個接口我們需要實現內部的方法binderDied,在onServiceConnected中通過linkToDeath設置代理,當binder意外死亡時會調用binderDied,我們需要在其中通過unlinkToDeath移除之前綁定的binder代理並重新綁定服務

private IBinder.DeathRecipient mDeathRecipient = new DeathRecipient() {

    @Override
    public void binderDied() {
       // TODO Auto-generated method stub
       Log.i(TAG, "binder is died");
       if (mIAidlManager == null)  
           return;  
       mIAidlManager.asBinder().unlinkToDeath(mDeathRecipient, 0);  
       mIAidlManager = null;  
       // TODO:重新綁定遠程服務
       ……
    }
 };

 private ServiceConnection conn = new ServiceConnection() {  

     @Override  
     public void onServiceDisconnected(ComponentName name) {  

     }  

     @Override  
     public void onServiceConnected(ComponentName name, IBinder service) {  
        mIAidlManager = mIAidlManager.Stub.asInterface(service);  
        try {  
            service.linkToDeath(mDeathRecipient, 0);  
            // TODO ……  
        } catch (RemoteException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
         }  
      }  
  };  

哦對了,關於binder通信的安全性方面,可以通過onBind是否返回null或者通過重寫Stub中的onTransact方法是否返回false來進行權限驗證,具體方式就不展開了,累……

總結一下(覺得下面這哥們寫的聽通俗的直接引用過來)如果有哪位同學覺得不對歡迎指正:
以下來自http://blog.csdn.net/hao707822882/article/details/40109045
binder機制概要:傳送的數據都是通過存放在driver的內核緩衝區中的,這樣client會向binder發送命令往這個共享區域寫數據,service的binder線程也會從這裏讀數據,過程是阻塞的,這樣線程安全。

第一點,在客戶端調用,實際是在和driver交互,不是在和service交互。

第二點:我們是怎麼獲取我們想要的service:所有的service都在servicemanager中註冊了,要找,向他要,那怎麼要呢?第三點

第三點:這要牽扯到serviceManager的註冊,serviceManager的註冊可以理解爲:在serviceManager啓動的時候,就會自告奮勇的申請成爲driver的上下文,至於上下文裏面的內容就是”xxxxx.xxx.xxxservice”=service這樣的引用,這些引用是怎麼生成的呢?第四點

第四點:當service要啓動的時候,會主動的先向driver得到serviceManager的引用,然後再向serviceManafger發送第三點當中提到的引用,而在service的啓動過程中,會通過driver在driver的內核空間創建一個共享的數據緩衝區(binder概要中提到的緩衝區就是這個),其實我個人觀點,你要是把第三點當中提到的註冊在servicemanager中的引用理解爲這個緩衝區的引用,也不錯,就是那麼回事

第五點:在service啓動的過程中,還啓動了許多的線程來處理binder驅動卸載緩衝區的數據,這就是binder線程
binder運行原理

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章