文章出處:鏈接:https://www.zhihu.com/question/39440766/answer/89210950
**在開始回答 前,先簡單概括性地說說Linux現有的所有進程間IPC方式:**
1. **管道:**在創建時分配一個page大小的內存,緩存區大小比較有限;
2. **消息隊列**:信息復制兩次,額外的CPU消耗;不合適頻繁或信息量大的通信;
3. **共享內存**:無須復制,共享緩沖區直接付附加到進程虛擬地址空間,速度快;但進程間的同步問題操作系統無法實現,必須各進程利用同步工具解決;
4. **套接字**:作為更通用的接口,傳輸效率低,主要用于不通機器或跨網絡的通信;
5. **信號量**:常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。因此,主要作為進程間以及同一進程內不同線程之間的同步手段。
6. **信號**: 不適用于信息交換,更適用于進程中斷控制,比如非法內存訪問,殺死某個進程等;
**Android的內核也是基于Linux內核,為何不直接采用Linux現有的進程IPC方案呢,難道Linux社區那么多優秀人員都沒有考慮到有Binder這樣一個更優秀的方案,是google太過于牛B嗎?事實是真相并非如此,請細細往下看,您就明白了。**
*****
**接下來正面回答這個問題,從5個角度來展開對Binder的分析:**
* **(1)從性能的角度** **數據拷貝次數:**Binder數據拷貝只需要一次,而管道、消息隊列、Socket都需要2次,但共享內存方式一次內存拷貝都不需要;從性能角度看,Binder性能僅次于共享內存。
* **(2)從穩定性的角度**
Binder是基于C/S架構的,簡單解釋下C/S架構,是指客戶端(Client)和服務端(Server)組成的架構,Client端有什么需求,直接發送給Server端去完成,架構清晰明朗,Server端與Client端相對獨立,穩定性較好;而共享內存實現方式復雜,沒有客戶與服務端之別, 需要充分考慮到訪問臨界資源的并發同步問題,否則可能會出現死鎖等問題;從這穩定性角度看,Binder架構優越于共享內存。
僅僅從以上兩點,各有優劣,還不足以支撐google去采用binder的IPC機制,那么更重要的原因是:
* **(3)從安全的角度**
傳統Linux IPC的接收方無法獲得對方進程可靠的UID/PID,從而無法鑒別對方身份;而Android作為一個開放的開源體系,擁有非常多的開發平臺,App來源甚廣,因此手機的安全顯得額外重要;對于普通用戶,絕不希望從App商店下載偷窺隱射數據、后臺造成手機耗電等等問題,傳統Linux IPC無任何保護措施,完全由上層協議來確保。
Android為每個安裝好的應用程序分配了自己的UID,故進程的UID是鑒別進程身份的重要標志,前面提到C/S架構,**Android系統中對外只暴露Client端,Client端將任務發送給Server端,Server端會根據權限控制策略,判斷UID/PID是否滿足訪問權限,目前權限控制很多時候是通過彈出權限詢問對話框,讓用戶選擇是否運行**。Android 6.0,也稱為Android M,在6.0之前的系統是在App第一次安裝時,會將整個App所涉及的所有權限一次詢問,只要留意看會發現很多App根本用不上通信錄和短信,但在這一次性權限權限時會包含進去,讓用戶拒絕不得,因為拒絕后App無法正常使用,而一旦授權后,應用便可以胡作非為。
針對這個問題,google在Android M做了調整,不再是安裝時一并詢問所有權限,而是在App運行過程中,需要哪個權限再彈框詢問用戶是否給相應的權限,對權限做了更細地控制,讓用戶有了更多的可控性,但**同時也帶來了另一個用戶詬病的地方,那也就是權限詢問的彈框的次數大幅度增多。**對于Android M平臺上,有些App開發者可能會寫出讓手機異常頻繁彈框的App,企圖直到用戶授權為止,這對用戶來說是不能忍的,用戶最后吐槽的可不光是App,還有Android系統以及手機廠商,有些用戶可能就跳果粉了,這還需要廣大Android開發者以及手機廠商共同努力,共同打造安全與體驗俱佳的Android手機。
Android中權限控制策略有SELinux等多方面手段,下面列舉從Binder的一個角度的權限控制:
[Android源碼的Binder權限是如何控制? -Gityuan的回答](https://www.zhihu.com/question/41003297/answer/89328987?from=profile_answer_card)
**傳統IPC**只能由用戶在數據包里填入UID/PID;另外,可靠的身份標記只有由IPC機制本身在內核中添加。其次傳統IPC訪問接入點是開放的,無法建立私有通道。從安全角度,Binder的安全性更高。
**說到這,可能有人要反駁**,Android就算用了Binder架構,而現如今Android手機的各種流氓軟件,不就是干著這種偷窺隱射,后臺偷偷跑流量的事嗎?沒錯,確實存在,但這不能說Binder的安全性不好,因為Android系統仍然是掌握主控權,可以控制這類App的流氓行為,只是對于該采用何種策略來控制,在這方面android的確存在很多有待進步的空間,這也是google以及各大手機廠商一直努力改善的地方之一。在Android 6.0,google對于app的權限問題作為較多的努力,大大收緊的應用權限;另外,在**Google舉辦的Android Bootcamp 2016**大會中,google也表示在Android 7.0 (也叫Android N)的權限隱私方面會進一步加強加固,比如SELinux,Memory safe language(還在research中)等等,在今年的5月18日至5月20日,google將推出Android N。
話題扯遠了,繼續說Binder。
* **(4)從語言層面的角度**
大家多知道Linux是基于C語言(面向過程的語言),而Android是基于Java語言(面向對象的語句),而對于Binder恰恰也符合面向對象的思想,將進程間通信轉化為通過對某個Binder對象的引用調用該對象的方法,而其獨特之處在于Binder對象是一個可以跨進程引用的對象,它的實體位于一個進程中,而它的引用卻遍布于系統的各個進程之中。可以從一個進程傳給其它進程,讓大家都能訪問同一Server,就像將一個對象或引用賦值給另一個引用一樣。Binder模糊了進程邊界,淡化了進程間通信過程,整個系統仿佛運行于同一個面向對象的程序之中。從語言層面,Binder更適合基于面向對象語言的Android系統,對于Linux系統可能會有點“水土不服”。
**另外,Binder是為Android這類系統而生,而并非Linux社區沒有想到Binder IPC機制的存在,對于Linux社區的廣大開發人員,我還是表示深深佩服,讓世界有了如此精湛而美妙的開源系統**。也并非Linux現有的IPC機制不夠好,相反地,經過這么多優秀工程師的不斷打磨,依然非常優秀,每種Linux的IPC機制都有存在的價值,同時在Android系統中也依然采用了大量Linux現有的IPC機制,根據每類IPC的原理特性,因時制宜,不同場景特性往往會采用其下最適宜的。比如在**Android OS中的Zygote進程的IPC采用的是Socket(套接字)機制**,Android中的**Kill Process采用的signal(信號)機制**等等。而**Binder更多則用在system\_server進程與上層App層的IPC交互**。
* **(5) 從公司戰略的角度**
總所周知,Linux內核是開源的系統,所開放源代碼許可協議GPL保護,該協議具有“病毒式感染”的能力,怎么理解這句話呢?受GPL保護的Linux Kernel是運行在內核空間,對于上層的任何類庫、服務、應用等運行在用戶空間,一旦進行SysCall(系統調用),調用到底層Kernel,那么也必須遵循GPL協議。
而Android 之父 Andy Rubin對于GPL顯然是不能接受的,為此,Google巧妙地將GPL協議控制在內核空間,將用戶空間的協議采用Apache-2.0協議(允許基于Android的開發商不向社區反饋源碼),同時在GPL協議與Apache-2.0之間的Lib庫中采用BSD證授權方法,有效隔斷了GPL的傳染性,仍有較大爭議,但至少目前緩解Android,讓GPL止步于內核空間,這是Google在GPL Linux下 開源與商業化共存的一個成功典范。
**有了這些鋪墊,我們再說說Binder的今世前緣**
Binder是基于開源的 [OpenBinder](https://link.zhihu.com/?target=http%3A//www.angryredplanet.com/~hackbod/openbinder/docs/html/BinderIPCMechanism.html)實現的,OpenBinder是一個開源的系統IPC機制,最初是由 [Be Inc.](https://link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Be_Inc.) 開發,接著由[Palm, Inc.](https://link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Palm%2C_Inc.)公司負責開發,現在OpenBinder的作者在Google工作,既然作者在Google公司,在用戶空間采用Binder 作為核心的IPC機制,再用Apache-2.0協議保護,自然而然是沒什么問題,減少法律風險,以及對開發成本也大有裨益的,那么從公司戰略角度,Binder也是不錯的選擇。
另外,再說一點關于OpenBinder,在2015年OpenBinder以及合入到Linux Kernel主線 3.19版本,這也算是Google對Linux的一點回饋吧。
**綜合上述5點,可知Binder是Android系統上層進程間通信的不二選擇。**
*****
**接著,回答樓主提到的**D-Bus
也采用C/S架構的IPC機制,**[D-Bus](https://link.zhihu.com/?target=https%3A//www.freedesktop.org/wiki/Software/dbus/)**是在用戶空間實現的方法,效率低,消息拷貝次數和上下文切換次數都明顯多過于Binder。針對D-Bus這些缺陷,于是就產生了**kdbus**,這是D-Bus在內核實現版,效率得到提升,與Binder一樣在內核作為字符設計,通過open()打開設備,mmap()映射內存。
(1)kdbus在進程間通信過程,Client端將消息在內存的消息隊列,可以存儲大量的消息,Server端不斷從消息隊里中取消息,大小只受限內存;
(2)Binder的機制是每次通信,會通信的進程或線程中的todo隊里中增加binder事務,并且每個進程所允許Binder線程數,google提供的默認最大線程數為16個,受限于CPU,由于線程數太多,增加系統負載,并且每個進程默認分配的(1M-8K)大小的內存。
而kdbus對于內存消耗較大,同時也適合傳輸大量數據和大量消息的系統。Binder對CPU和內存的需求比較低,效率比較高,從而進一步說明Binder適合于移動系統Android,但是,也有一定缺點,就是不同利用Binder輸出大數據,比如利用Binder傳輸幾M大小的圖片,便會出現異常,雖然有廠商會增加Binder內存,但是也不可能比系統默認內存大很多,否則整個系統的可用內存大幅度降低。
**最后,簡單講講Android Binder架構**
Binder在Android系統中江湖地位非常之高。在Zygote孵化出system\_server進程后,在system\_server進程中出初始化支持整個Android framework的各種各樣的Service,而這些Service從大的方向來劃分,分為Java層Framework和Native Framework層(C++)的Service,幾乎都是基于BInder IPC機制。
1. **Java framework:作為Server端繼承(或間接繼承)于Binder類,Client端繼承(或間接繼承)于BinderProxy類**。例如 ActivityManagerService(用于控制Activity、Service、進程等) 這個服務作為Server端,間接繼承Binder類,而相應的ActivityManager作為Client端,間接繼承于BinderProxy類。 當然還有PackageManagerService、WindowManagerService等等很多系統服務都是采用C/S架構;
2. **Native Framework層:這是C++層,作為Server端繼承(或間接繼承)于BBinder類,Client端繼承(或間接繼承)于BpBinder**。例如MediaPlayService(用于多媒體相關)作為Server端,繼承于BBinder類,而相應的MediaPlay作為Client端,間接繼承于BpBinder類。
**總之,一句話"無Binder不Android"。**
- 前言
- Android系統的體系結構
- Dalvik VM 和 JVM 的比較
- Android 打包應用程序并安裝的過程
- Android ADB工具
- Android應用開發
- Android UI相關知識總結
- Android 中window 、view、 Activity的關系
- Android應用界面
- Android中的drawable和bitmap
- AndroidUI組件adapterView及其子類和Adapter的關系
- Android四大組件
- Android 數據存儲
- SharedPreference
- Android應用的資源
- 數組資源
- 使用Drawable資源
- Material Design
- Android 進程和線程
- 進程
- 線程
- Android Application類的介紹
- 意圖(Intent)
- Intent 和 Intent 過濾器(Google官網介紹)
- Android中關于任務棧的總結
- 任務和返回棧(官網譯文)
- 總結
- Android應用安全現狀與解決方案
- Android 安全開發
- HTTPS
- 安卓 代碼混淆與打包
- 動態注入技術(hook技術)
- 一、什么是hook技術
- 二、常用的Hook 工具
- Xposed源碼剖析——概述
- Xposed源碼剖析——app_process作用詳解
- Xposed源碼剖析——Xposed初始化
- Xposed源碼剖析——hook具體實現
- 無需Root也能Hook?——Depoxsed框架演示
- 三、HookAndroid應用
- 四、Hook原生應用程序
- 五、Hook 檢測/修復
- Android 應用的逆向與加固保護技術
- OpenCV在Android中的開發
- Android高級開發進階
- 高級UI
- UI繪制流程及原理
- Android新布局ConstraintLayout約束布局
- 關鍵幀動畫
- 幀動畫共享元素變換
- Android異步消息處理機制完全解析,帶你從源碼的角度徹底理解
- Android中為什么主線程不會因為Looper.loop()里的死循環卡死?
- 為什么 Android 要采用 Binder 作為 IPC 機制?
- JVM 中一個線程的 Java 棧和寄存器中分別放的是什么?
- Android源碼的Binder權限是如何控制?
- 如何詳解 Activity 的生命周期?
- 為什么Android的Handler采用管道而不使用Binder?
- ThreadLocal,你真的懂了嗎?
- Android屏幕刷新機制