02.Android之IPC機制問題

目錄介紹

  • 2.0.0.1 什麼是Binder?爲何要使用Binder?Binder中是如何進行線程管理的?總結binder講的是什麼?
  • 2.0.0.2 Android中進程和線程的關係?什麼是IPC?爲什麼須要進行IPC?多進程通訊可能會出現什麼問題?
  • 2.0.0.3 Binder的工做流程是怎樣的?Binder主要能提供哪些功能?Binder通訊機制原理是怎樣的?
  • 2.0.0.4 Android中爲什麼新增Binder來做爲主要的IPC方式?Binder運行機制是怎樣的?Binder機制有什麼優點?
  • 2.0.0.5 Android中跨進程通信的幾種方式?實際開發中,有哪些場景使用Binder進行數據傳輸?
  • 2.0.0.6 Android中有哪些基於Binder的IPC方式?簡單對比下?
  • 2.0.0.7 爲什麼說Binder相比傳統的Socket性能更高效?爲什麼說Binder相比傳統IPC安全性更高?
  • 2.0.0.8 Service Manager是如何成爲一個守護進程的?Server和Client是如何得到Service Manager接口的?

好消息

  • 博客筆記大彙總【15年10月到至今】,包括Java基礎及深刻知識點,Android技術博客,Python學習筆記等等,還包括平時開發中遇到的bug彙總,固然也在工做之餘收集了大量的面試題,長期更新維護而且修正,持續完善……開源的文件是markdown格式的!同時也開源了生活博客,從12年起,積累共計500篇[近100萬字],將會陸續發表到網上,轉載請註明出處,謝謝!
  • 連接地址:https://github.com/yangchong2...
  • 若是以爲好,能夠star一下,謝謝!固然也歡迎提出建議,萬事起於忽微,量變引發質變!全部的筆記將會更新到GitHub上,同時保持更新,歡迎同行提出或者push不一樣的見解或者筆記!

2.0.0.1 什麼是Binder?爲何要使用Binder?Binder中是如何進行線程管理的?總結binder講的是什麼?

  • 什麼是Binder?php

    • 1.直觀來講,Binder是Android中的一個類,它繼承了IBinder接口
    • 2.從IPC角度來講,Binder是Android中的一種跨進程通訊方式,Binder還能夠理解爲一種虛擬的物理設備,它的設備驅動是/dev/binder,該通訊方式在linux中沒有
    • 3.從Android Framework角度來講,Binder是ServiceManager鏈接各類Manager(ActivityManager、WindowManager,etc)和相應ManagerService的橋樑
    • 4.從Android應用層來講,Binder是客戶端和服務端進行通訊的媒介,當你bindService的時候,服務端會返回一個包含了服務端業務調用的Binder對象,經過這個Binder對象,客戶端就能夠獲取服務端提供的服務或者數據,這裏的服務包括普通服務和基於AIDL的服務。
  • 爲何要使用Binder?技術博客大總結linux

    • 在傳統的Linux上,咱們仍是有不少選擇能夠用來實現進程間通訊,如管道、SystemV、Socket等。那麼Android爲何不使用這些原有的技術,而是要使開發一種新的叫Binder的進程間通訊機制呢?
    • 最簡單的回答:性能:相比傳統的Socket更高效;安全:安全性高,支持通訊雙方進行身份驗證。
    • 詳細一點說,主要有兩個方面的緣由:android

      • 性能方面git

        • 在移動設備上(性能受限制的設備,好比要省電),普遍地使用跨進程通訊對通訊機制的性能有嚴格的要求,Binder相對出傳統的Socket方式,更加高效。Binder數據拷貝只須要一次,而管道、消息隊列、Socket都須要2次,共享內存方式一次內存拷貝都不須要,但實現方式又比較複雜。
      • 安全方面github

        • 傳統的進程通訊方式對於通訊雙方的身份並無作出嚴格的驗證,好比Socket通訊ip地址是客戶端手動填入,很容易進行僞造,而Binder機制從協議自己就支持對通訊雙方作身份校檢,於是大大提高了安全性。
      • 還有一些好處,如實現面象對象的調用方式,在使用Binder時就和調用一個本地實例同樣。
  • Binder中是如何進行線程管理的?面試

    • 每一個Binder的Server進程會建立不少線程來處理Binder請求,能夠簡單的理解爲建立了一個Binder的線程池吧(雖然實際上並不徹底是這樣簡單的線程管理方式),而真正管理這些線程並非由這個Server端來管理的,而是由Binder驅動進行管理的。
    • 一個進程的Binder線程數默認最大是16,超過的請求會被阻塞等待空閒的Binder線程。理解這一點的話,你作進程間通訊時處理併發問題就會有一個底,好比使用ContentProvider時(又一個使用Binder機制的組件),你就很清楚它的CRUD(建立、檢索、更新和刪除)方法只能同時有16個線程在跑。
  • 總結binder講的是什麼?segmentfault

    • 一般意義上來講,Binder就是指Andriod的通訊機制;
    • 對於服務端進程來講,Binder指的是Binder本地對象,對於客戶端進程來講,Binder指的是Binder代理對象。
    • 對於傳輸過程來講,Binder是能夠進行跨進程傳遞的對象;

2.0.0.2 Android中進程和線程的關係?什麼是IPC?爲什麼須要進行IPC?多進程通訊可能會出現什麼問題?

  • Android中進程和線程的關係?緩存

    • 一個APP通常對應一個進程和有限個線程安全

      • 通常對應一個進程,固然,能夠在AndroidMenifest中給四大組件指定屬性android:process開啓多進程模式
      • 有限個線程:線程是一種受限的系統資源,不可無限制的產生且線程的建立和銷燬都有必定的開銷。
  • 什麼是IPC?
  • 爲什麼須要進行IPC?服務器

    • 進程間通訊的必要性
    • 全部運行在不一樣進程的四大組件,只要它們之間須要經過內存在共享數據,都會共享失敗。這是因爲Android爲每一個應用分配了獨立的虛擬機,不一樣的虛擬機在內存分配上有不一樣的地址空間,這會致使在不一樣的虛擬機中訪問同一個類的對象會產生多份副本。技術博客大總結
  • 多進程形成的影響可總結爲如下四方面

    • 靜態變量和單例模式失效:由獨立的虛擬機形成
    • 線程同步機制失效:由獨立的虛擬機形成
    • SharedPreference的不可靠降低:不支持兩個進程同時進行讀寫操做,即不支持併發讀寫,有必定概率致使數據丟失
    • Application屢次建立:Android系統會爲新的進程分配獨立虛擬機,至關於系統又把這個應用從新啓動了一次。

2.0.0.3 Binder的工做流程是怎樣的?Binder主要能提供哪些功能?Binder通訊機制原理是怎樣的?

  • Binder的工做流程是怎樣的?

    • 1客戶端首先獲取服務器端的代理對象。所謂的代理對象實際上就是在客戶端創建一個服務端的「引用」,該代理對象具備服務端的功能,使其在客戶端訪問服務端的方法就像訪問本地方法同樣。
    • 2客戶端經過調用服務器代理對象的方式向服務器端發送請求。
    • 3代理對象將用戶請求經過Binder驅動發送到服務器進程。
    • 4服務器進程處理用戶請求,並經過Binder驅動返回處理結果給客戶端的服務器代理對象。
    • 5客戶端收到服務端的返回結果。
  • binder工做流程圖以下所示:

    • image
  • Binder主要能提供哪些功能?

    • 用驅動程序來推動進程間的通訊。
    • 經過共享內存來提升性能。
    • 爲進程請求分配每一個進程的線程池。
    • 針對系統中的對象引入了引用計數和跨進程的對象引用映射。
    • 進程間同步調用。
  • Binder通訊機制原理是怎樣的?

    • image
    • Server進程向ServiceManager註冊,告訴ServiceManager我是誰,我有什麼,我能作什麼。就比如徐同窗(Server進程)有一臺筆記本(computer對象),這檯筆記本有個add方法。這時映射關係表就生成了。技術博客大總結
    • Client進程向ServiceManager查詢,我要調用Server進程的computer對象的add方法,能夠看到這個過程通過Binder驅動,這時候Binder驅動就開始發揮他的做用了。當向ServiceManager查詢完畢,是返回一個computer對象給Client進程嗎?其實否則,Binder驅動將computer對象轉換成了computerProxy對象,並轉發給了Client進程,所以,Client進程拿到的並非真實的computer對象,而是一個代理對象,即computerProxy對象。很容易理解這個computerProxy對象也是有add方法,(若是連add方法都沒有,豈不是欺騙了Client?),可是這個add方法只是對參數進行一些包裝而已。
    • 當Client進程調用add方法,這個消息發送給Binder驅動,這時驅動發現,原來是computerProxy,那麼Client進程應該是須要調用computer對象的add方法的,這時驅動通知Server進程,調用你的computer對象的add方法,將結果給我。而後Server進程就將計算結果發送給驅動,驅動再轉發給Client進程,這時Client進程還蒙在了鼓裏,他覺得本身調用的是真實的computer對象的add方法,其實他只是調用了代理而已。不過Client最終仍是拿到了計算結果。

2.0.0.4 Android中爲什麼新增Binder來做爲主要的IPC方式?Binder運行機制是怎樣的?Binder機制有什麼優點?

  • Binder運行機制是怎樣的?

    • Binder基於Client-Server通訊模式,除了Client端和Server端,還有兩角色一塊兒合做完成進程間通訊功能。
    • Binder通訊的四個角色:

      • Client進程:使用服務的進程。
      • Server進程:提供服務的進程。
      • ServiceManager進程:ServiceManager的做用是將字符形式的Binder名字轉化成Client中對該Binder的引用,使得Client可以經過Binder名字得到對Server中Binder實體的引用。
      • Binder驅動:驅動負責進程之間Binder通訊的創建,Binder在進程之間的傳遞,Binder引用計數管理,數據包在進程之間的傳遞和交互等一系列底層支持。
    • 接觸這些概念可能會以爲難於理解,讀者能夠把四個角色和熟悉的互聯網進行類比:Server是服務器,Client是客戶終端,ServiceManager是域名服務器(DNS),驅動是路由器。
  • Binder機制有什麼優點

    • 傳輸效率高、可操做性強:傳輸效率主要影響因素是內存拷貝的次數,拷貝次數越少,傳輸速率越高。從Android進程架構角度分析:對於消息隊列、Socket和管道來講,數據先從發送方的緩存區拷貝到內核開闢的緩存區中,再從內核緩存區拷貝到接收方的緩存區,一共兩次拷貝
    • 技術博客大總結
    • 對於Binder來講,數據從發送方的緩存區拷貝到內核的緩存區,而接收方的緩存區與內核的緩存區是映射到同一塊物理地址的,節省了一次數據拷貝的過程
    • 因爲共享內存操做複雜,綜合來看,Binder的傳輸效率是最好的。
    • 實現C/S架構方便:Linux的衆IPC方式除了Socket之外都不是基於C/S架構,而Socket主要用於網絡間的通訊且傳輸效率較低。Binder基於C/S架構 ,Server端與Client端相對獨立,穩定性較好。
    • 安全性高:傳統Linux IPC的接收方沒法得到對方進程可靠的UID/PID,從而沒法鑑別對方身份;而Binder機制爲每一個進程分配了UID/PID且在Binder通訊時會根據UID/PID進行有效性檢測。

2.0.0.5 Android中跨進程通信的幾種方式?實際開發中,有哪些場景使用Binder進行數據傳輸?

  • Android中跨進程通信的幾種方式?

    • Android 跨進程通訊,像intent,contentProvider,廣播,service均可以跨進程通訊。

      • intent:這種跨進程方式並非訪問內存的形式,它須要傳遞一個uri,好比說打電話。
      • contentProvider:這種形式,是使用數據共享的形式進行數據共享。
      • service:遠程服務,aidl
      • 廣播技術博客大總結
  • 實際開發中,有哪些場景使用Binder進行數據傳輸?

    • 經過AIDL實現方式解釋Binder數據傳輸的具體過程

      • 服務端中的Service給與其綁定的客戶端提供Binder對象,客戶端經過AIDL接口中的asInterface()將這個Binder對象轉換爲代理Proxy,並經過它發起RPC請求。客戶端發起請求時會掛起當前線程,並將參數寫入data而後調用transact(),RPC請求會經過系統底層封裝後由服務端的onTransact()處理,並將結果寫入reply,最後返回調用結果並喚醒客戶端線程。
    • AIDL原理是什麼?如何優化多模塊都使用AIDL的狀況?

      • AIDL(Android Interface Definition Language,Android接口定義語言):若是在一個進程中要調用另外一個進程中對象的方法,可以使用AIDL生成可序列化的參數,AIDL會生成一個服務端對象的代理類,經過它客戶端實現間接調用服務端對象的方法。
      • AIDL的本質是系統提供了一套可快速實現Binder的工具。關鍵類和方法:
      AIDL接口:繼承IInterface。
      Stub類:Binder的實現類,服務端經過這個類來提供服務。
      Proxy類:服務器的本地代理,客戶端經過這個類調用服務器的方法。
      asInterface():客戶端調用,將服務端的返回的Binder對象,轉換成客戶端所須要的AIDL接口類型對象。返回對象:
          若客戶端和服務端位於同一進程,則直接返回Stub對象自己;
          不然,返回的是系統封裝後的Stub.proxy對象。
      asBinder():根據當前調用狀況返回代理Proxy的Binder對象。
      onTransact():運行服務端的Binder線程池中,當客戶端發起跨進程請求時,遠程請求會經過系統底層封裝後交由此方法來處理。
      transact():運行在客戶端,當客戶端發起遠程請求的同時將當前線程掛起。以後調用服務端的onTransact()直到遠程請求返回,當前線程才繼續執行。
      • 當有多個業務模塊都須要AIDL來進行IPC,此時須要爲每一個模塊建立特定的aidl文件,那麼相應的Service就會不少。必然會現系統資源耗費嚴重、應用過分重量級的問題。解決辦法是創建Binder鏈接池,即將每一個業務模塊的Binder請求統一轉發到一個遠Service中去執行,從而避免重複建立Service。
      • 工做原理:每一個業務模塊建立本身的AIDL接口並實現此接口,而後向服務端提供本身的惟一標識和其對應的Binder對象。服務端只須要一個Service,服務器提供一個queryBinder接口,它會根據業務模塊的特徵來返回相應的Binder對像,不一樣的業務模塊拿到所需的Binder對象後就可進行遠程方法的調用了。

2.0.0.6 Android中有哪些基於Binder的IPC方式?簡單對比下?

  • image

2.0.0.7 爲什麼說Binder相比傳統的Socket性能更高效?爲什麼說Binder相比傳統IPC安全性更高?

  • 爲什麼說Binder相比傳統的Socket性能更高效?

    • 跨進程通信中,只有socket支持Client-Server的通訊方式,可是socket做爲一款通用接口,其傳輸效率低,開銷大,主要用在跨網絡的進程間通訊和本機上進程間的低速通訊。
    • 消息隊列和管道採用存儲-轉發方式,即數據先從發送方緩存區拷貝到內核開闢的緩存區中,而後再從內核緩存區拷貝到接收方緩存區,至少有兩次拷貝過程。
    • 共享內存雖然無需拷貝,但控制複雜,難以使用。
  • 爲什麼說Binder相比傳統IPC安全性更高?

    • 首先傳統IPC的接收方沒法得到對方進程可靠的UID和PID(用戶ID進程ID),從而沒法鑑別對方身份。Android爲每一個安裝好的應用程序分配了本身的UID,故進程的UID是鑑別進程身份的重要標誌。使用傳統IPC只能由用戶在數據包裏填入UID和PID,但這樣不可靠,容易被惡意程序利用。可靠的身份標記只有由IPC機制自己在內核中添加。其次傳統IPC訪問接入點是開放的,沒法創建私有通道。好比命名管道的名稱,systemV的鍵值,socket的ip地址或文件名都是開放的,只要知道這些接入點的程序均可以和對端創建鏈接,無論怎樣都沒法阻止惡意程序經過猜想接收方地址得到鏈接。
    • 基於以上緣由,Android須要創建一套新的IPC機制來知足系統對通訊方式,傳輸性能和安全性的要求,這就是Binder。
    • Binder基於Client-Server通訊模式,傳輸過程只需一次拷貝,爲發送發添加UID/PID身份,既支持實名Binder也支持匿名Binder,安全性高。技術博客大總結

2.0.0.8 Service Manager是如何成爲一個守護進程的?Server和Client是如何得到Service Manager接口的?

  • Service Manager是如何成爲一個守護進程的?

    • Service Manager,它是整個Binder機制的守護進程,用來管理開發者建立的各類Server,而且向Client提供查詢Server遠程接口的功能技術博客大總結
    • 既然Service Manager組件是用來管理Server而且向Client提供查詢Server遠程接口的功能,那麼,Service Manager就必然要和Server以及Client進行通訊了。咱們知道,Service Manger、Client和Server三者分別是運行在獨立的進程當中,這樣它們之間的通訊也屬於進程間通訊了,並且也是採用Binder機制進行進程間通訊,所以,Service Manager在充當Binder機制的守護進程的角色的同時,也在充當Server的角色,然而,它是一種特殊的Server,下面咱們將會看到它的特殊之處
    • Service Manager在用戶空間的源代碼位於frameworks/base/cmds/servicemanager目錄下,主要是由binder.h、binder.c和service_manager.c三個文件組成。Service Manager的入口位於service_manager.c文件中的main函數:

      int main(int argc, char **argv){
          struct binder_state *bs;
          void *svcmgr = BINDER_SERVICE_MANAGER;
          bs = binder_open(128*1024);
          if (binder_become_context_manager(bs)) {
              LOGE("cannot become context manager (%s)\n", strerror(errno));
              return -1;
          }
          svcmgr_handle = svcmgr;
          binder_loop(bs, svcmgr_handler);
          return 0;
      }
    • main函數主要有三個功能:一是打開Binder設備文件;二是告訴Binder驅動程序本身是Binder上下文管理者,即咱們前面所說的守護進程;三是進入一個無窮循環,充當Server的角色,等待Client的請求
  • Server和Client是如何得到Service Manager接口的?

    • ServiceManager做爲守護進程,Service Manager的職責固然就是爲Server和Client服務了。那麼,Server和Client如何得到Service Manager接口,進而享受它提供的服務呢?
    • Service Manager在Binder機制中既充當守護進程的角色,同時它也充當着Server角色,然而它又與通常的Server不同。對於普通的Server來講,Client若是想要得到Server的遠程接口,那麼必須經過Service Manager遠程接口提供的getService接口來得到,這自己就是一個使用Binder機制來進行進程間通訊的過程。而對於Service Manager這個Server來講,Client若是想要得到Service Manager遠程接口,卻沒必要經過進程間通訊機制來得到,由於Service Manager遠程接口是一個特殊的Binder引用,它的引用句柄必定是0。
    • 通過一系列的調用...
    • 回到defaultServiceManager函數中,最終結果爲:gDefaultServiceManager = new BpServiceManager(new BpBinder(0));
    • 這樣,Service Manager遠程接口就建立完成了,它本質上是一個BpServiceManager,包含了一個句柄值爲0的Binder引用。技術博客大總結
  • 在Android系統的Binder機制中,Server和Client拿到這個Service Manager遠程接口以後怎麼用呢?

    • 對Server來講,就是調用IServiceManager::addService這個接口來和Binder驅動程序交互了,即調用BpServiceManager::addService 。而BpServiceManager::addService又會調用經過其基類BpRefBase的成員函數remote得到原先建立的BpBinder實例,接着調用BpBinder::transact成員函數。在BpBinder::transact函數中,又會調用IPCThreadState::transact成員函數,這裏就是最終與Binder驅動程序交互的地方了。回憶一下前面的類圖,IPCThreadState有一個PorcessState類型的成中變量mProcess,而mProcess有一個成員變量mDriverFD,它是設備文件/dev/binder的打開文件描述符,所以,IPCThreadState就至關於間接在擁有了設備文件/dev/binder的打開文件描述符,因而,即可以與Binder驅動程序交互了。
    • 對Client來講,就是調用IServiceManager::getService這個接口來和Binder驅動程序交互了。具體過程上述Server使用Service Manager的方法是差很少的。

關於其餘內容介紹

01.關於博客彙總連接

02.關於個人博客

相關文章
相關標籤/搜索