02.Android之IPC机制问题
生活随笔
收集整理的這篇文章主要介紹了
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萬字],將會陸續發表到網上,轉載請注明出處,謝謝!
- 鏈接地址:github.com/yangchong21…
- 如果覺得好,可以star一下,謝謝!當然也歡迎提出建議,萬事起于忽微,量變引起質變!所有的筆記將會更新到GitHub上,同時保持更新,歡迎同行提出或者push不同的看法或者筆記!
2.0.0.1 什么是Binder?為什么要使用Binder?Binder中是如何進行線程管理的?總結binder講的是什么?
- 什么是Binder?
- 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上,我們還是有很多選擇可以用來實現進程間通信,如管道、SystemV、Socket等。那么Android為什么不使用這些原有的技術,而是要使開發一種新的叫Binder的進程間通信機制呢?
- 最簡單的回答:性能:相比傳統的Socket更高效;安全:安全性高,支持通信雙方進行身份驗證。
- 詳細一點說,主要有兩個方面的原因:
- 性能方面
- 在移動設備上(性能受限制的設備,比如要省電),廣泛地使用跨進程通信對通信機制的性能有嚴格的要求,Binder相對出傳統的Socket方式,更加高效。Binder數據拷貝只需要一次,而管道、消息隊列、Socket都需要2次,共享內存方式一次內存拷貝都不需要,但實現方式又比較復雜。
- 安全方面
- 傳統的進程通信方式對于通信雙方的身份并沒有做出嚴格的驗證,比如Socket通信ip地址是客戶端手動填入,很容易進行偽造,而Binder機制從協議本身就支持對通信雙方做身份校檢,因而大大提升了安全性。
- 還有一些好處,如實現面象對象的調用方式,在使用Binder時就和調用一個本地實例一樣。
- 性能方面
- Binder中是如何進行線程管理的?
- 每個Binder的Server進程會創建很多線程來處理Binder請求,可以簡單的理解為創建了一個Binder的線程池吧(雖然實際上并不完全是這樣簡單的線程管理方式),而真正管理這些線程并不是由這個Server端來管理的,而是由Binder驅動進行管理的。
- 一個進程的Binder線程數默認最大是16,超過的請求會被阻塞等待空閑的Binder線程。理解這一點的話,你做進程間通信時處理并發問題就會有一個底,比如使用ContentProvider時(又一個使用Binder機制的組件),你就很清楚它的CRUD(創建、檢索、更新和刪除)方法只能同時有16個線程在跑。
- 總結binder講的是什么?
- 通常意義上來說,Binder就是指Andriod的通信機制;
- 對于服務端進程來說,Binder指的是Binder本地對象,對于客戶端進程來說,Binder指的是Binder代理對象。
- 對于傳輸過程來說,Binder是可以進行跨進程傳遞的對象;
2.0.0.2 Android中進程和線程的關系?什么是IPC?為何需要進行IPC?多進程通信可能會出現什么問題?
- Android中進程和線程的關系?
- 一個APP一般對應一個進程和有限個線程
- 一般對應一個進程,當然,可以在AndroidMenifest中給四大組件指定屬性android:process開啟多進程模式
- 有限個線程:線程是一種受限的系統資源,不可無限制的產生且線程的創建和銷毀都有一定的開銷。
- 一個APP一般對應一個進程和有限個線程
- 什么是IPC?
- 為何需要進行IPC?
- 進程間通信的必要性
- 所有運行在不同進程的四大組件,只要它們之間需要通過內存在共享數據,都會共享失敗。這是由于Android為每個應用分配了獨立的虛擬機,不同的虛擬機在內存分配上有不同的地址空間,這會導致在不同的虛擬機中訪問同一個類的對象會產生多份副本。技術博客大總結
- 多進程造成的影響可總結為以下四方面
- 靜態變量和單例模式失效:由獨立的虛擬機造成
- 線程同步機制失效:由獨立的虛擬機造成
- SharedPreference的不可靠下降:不支持兩個進程同時進行讀寫操作,即不支持并發讀寫,有一定幾率導致數據丟失
- Application多次創建:Android系統會為新的進程分配獨立虛擬機,相當于系統又把這個應用重新啟動了一次。
2.0.0.3 Binder的工作流程是怎樣的?Binder主要能提供哪些功能?Binder通信機制原理是怎樣的?
- Binder的工作流程是怎樣的?
- 1客戶端首先獲取服務器端的代理對象。所謂的代理對象實際上就是在客戶端建立一個服務端的“引用”,該代理對象具有服務端的功能,使其在客戶端訪問服務端的方法就像訪問本地方法一樣。
- 2客戶端通過調用服務器代理對象的方式向服務器端發送請求。
- 3代理對象將用戶請求通過Binder驅動發送到服務器進程。
- 4服務器進程處理用戶請求,并通過Binder驅動返回處理結果給客戶端的服務器代理對象。
- 5客戶端收到服務端的返回結果。
- binder工作流程圖如下所示:
- Binder主要能提供哪些功能?
- 用驅動程序來推進進程間的通信。
- 通過共享內存來提高性能。
- 為進程請求分配每個進程的線程池。
- 針對系統中的對象引入了引用計數和跨進程的對象引用映射。
- 進程間同步調用。
- Binder通信機制原理是怎樣的?
- 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
- 廣播技術博客大總結
- Android 跨進程通信,像intent,contentProvider,廣播,service都可以跨進程通信。
- 實際開發中,有哪些場景使用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來進行IPC,此時需要為每個模塊創建特定的aidl文件,那么相應的Service就會很多。必然會現系統資源耗費嚴重、應用過度重量級的問題。解決辦法是建立Binder連接池,即將每個業務模塊的Binder請求統一轉發到一個遠Service中去執行,從而避免重復創建Service。
- 工作原理:每個業務模塊創建自己的AIDL接口并實現此接口,然后向服務端提供自己的唯一標識和其對應的Binder對象。服務端只需要一個Service,服務器提供一個queryBinder接口,它會根據業務模塊的特征來返回相應的Binder對像,不同的業務模塊拿到所需的Binder對象后就可進行遠程方法的調用了。
- 通過AIDL實現方式解釋Binder數據傳輸的具體過程
2.0.0.6 Android中有哪些基于Binder的IPC方式?簡單對比下?
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.關于博客匯總鏈接
- 1.技術博客匯總
- 2.開源項目匯總
- 3.生活博客匯總
- 4.喜馬拉雅音頻匯總
- 5.其他匯總
02.關于我的博客
- 我的個人站點:www.yczbj.org, www.ycbjie.cn
- github:github.com/yangchong21…
- 知乎:www.zhihu.com/people/yczb…
- 簡書:www.jianshu.com/u/b7b2c6ed9…
- csdn:my.csdn.net/m0_37700275
- 喜馬拉雅聽書:www.ximalaya.com/zhubo/71989…
- 開源中國:my.oschina.net/zbj1618/blo…
- 泡在網上的日子:www.jcodecraeer.com/member/cont…
- 郵箱:yangchong211@163.com
- 阿里云博客:yq.aliyun.com/users/artic… 239.headeruserinfo.3.dT4bcV
- segmentfault頭條:segmentfault.com/u/xiangjian…
- 掘金:juejin.im/user/593943…
總結
以上是生活随笔為你收集整理的02.Android之IPC机制问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 记一次laravel-jwt修改黑名单所
- 下一篇: Kong 1.0正式发布,提供服务网格支