Android IPC 機制分析
Android IPC 機制分析
android核心是基於Linux核心的,首先來說一下Linux現有的程式間IPC方式:
- 管道: 在建立時分配一個page大小的記憶體,快取區大小比較有限;
- 訊息佇列: 資訊複製兩次,額外的CPU消耗;不合適頻繁或資訊量大的通訊;
- 共享記憶體: 無須複製,共享緩衝區直接付附加到程式虛擬地址空間,速度快;但程式間的同步問題作業系統無法實現,必須各程式利用同步工具解決;
- 套接字: 作為更通用的介面,傳輸效率低,主要用於不通機器或跨網路的通訊;
- 訊號量: 常作為一種鎖機制,防止某程式正在訪問共享資源時,其他程式也訪問該資源。因此,主要作為程式間以及同一程式內不同執行緒之間的同步手段。
- 訊號: 不適用於資訊交換,更適用於程式中斷控制,比如非法記憶體訪問,殺死某個程式等;
接下來我們說一說Binder。
Binder是基於開源的 OpenBinder實現的,OpenBinder是一個開源的系統IPC機制,最初是由 Be Inc. 開發,接著由Palm, Inc.公司負責開發,現在OpenBinder的作者在Google工作,既然作者在Google公司,在使用者空間採用Binder 作為核心的IPC機制,再用Apache-2.0協議保護,自然而然是沒什麼問題,減少法律風險,以及對開發成本也大有裨益的,那麼從公司戰略角度,Binder也是不錯的選擇。
另外,再說一點關於OpenBinder,在2015年OpenBinder已經合入到Linux Kernel主線 3.19版本,這也算是Google對Linux的一點回饋吧。
下面我們對Binder和其他IPC方式從5個角進行詳細的分析:
- 從效能角度分析: Binder資料拷貝只需要一次,而管道、訊息佇列、Socket都需要2次,但共享記憶體方式一次記憶體拷貝都不需要;從效能角度看,Binder效能僅次於共享記憶體。
- 從穩定性角度分析: Binder是基於C/S架構的,簡單解釋下C/S架構,是指客戶端(Client)和服務端(Server)組成的架構,Client端有什麼需求,直接傳送給Server端去完成,架構清晰明朗,Server端與Client端相對獨立,穩定性較好;而共享記憶體實現方式複雜,沒有客戶端與服務端之別, 需要充分考慮到訪問臨界資源的併發同步問題,否則可能會出現死鎖等問題;從這穩定性角度看,Binder架構優越於共享記憶體。
僅僅從以上兩點,各有優劣,還不足以支撐google去採用binder的IPC機制,那麼更重要的原因是:
-
從安全性角度分析: 傳統的Linux IPC的接收方法無法獲得對方程式可靠的UID/PID,從而無法鑑別對方身份;而Android作為一個開放的開源體系,擁有非常多的開發平臺,App來源甚廣,因此手機的安全顯得額外重要;對於普通使用者,絕不希望從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的一個角度的許可權控制:
傳統IPC只能由使用者在資料包裡填入UID/PID;另外,可靠的身份標記只有由IPC機制本身在核心中新增。其次傳統IPC訪問接入點是開放的,無法建立私有通道。從安全形度,Binder的安全性更高。 -
從語言層面的角度分析: 大家多知道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互動。 -
從公司戰略角度分析: 眾所周知,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下 開源與商業化共存的一個成功典範。
綜合上述5點,可知Binder是Android系統上層程式間通訊的不二選擇。
D-Bus也採用C/S架構的IPC機制,D-Bus是在使用者空間實現的方法,效率低,訊息拷貝次數和上下文切換次數都明顯多過於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機制。
- Java framework:作為Server端繼承(或間接繼承)於Binder類,Client端繼承(或間接繼承)於BinderProxy類。 例如 ActivityManagerService(用於控制Activity、Service、程式等) 這個服務作為Server端,間接繼承Binder類,而相應的ActivityManager作為Client端,間接繼承於BinderProxy類。 當然還有PackageManagerService、WindowManagerService等等很多系統服務都是採用C/S架構;
- Native Framework層:這是C++層,作為Server端繼承(或間接繼承)於BBinder類,Client端繼承(或間接繼承)於BpBinder。 例如MediaPlayService(用於多媒體相關)作為Server端,繼承於BBinder類,而相應的MediaPlay作為Client端,間接繼承於BpBinder類。
連結:https://www.zhihu.com/question/39440766/answer/89210950
來源:知乎
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
相關文章
- 02.Android之IPC機制問題Android
- Android IPC機制(三):淺談Binder的使用Android
- 詳解 Android 中的 IPC 機制:基礎篇Android
- 學習筆記(2)IPC機制筆記
- Android 原始碼分析(二)handler 機制Android原始碼
- Binder通訊機制與IPC通訊.md
- android的TouchEvent派發機制的分析Android
- Android IPC 之AIDLAndroidAI
- 真香!為什麼Android要採用Binder作為IPC機制?全套教學資料Android
- 原始碼分析:Android訊息處理機制原始碼Android
- 基於原始碼分析 Android View 繪製機制原始碼AndroidView
- Android Classloader機制Android
- Android NestedScrolling機制Android
- 基於原始碼分析 Android View 事件分發機制原始碼AndroidView事件
- 「Android」分析EventBus原始碼擴充套件Weex事件機制Android原始碼套件事件
- android中反射機制Android反射
- Android簽名機制Android
- Android包管理機制Android
- android 非同步通訊機制Handler的分析與運用Android非同步
- Android Handler機制之Message及Message回收機制Android
- Android系統安全機制Android
- 理解 Android 訊息機制Android
- Android訊息機制HandlerAndroid
- Android重修課 -- Parcel機制Android
- Android事件分發機制Android事件
- android訊息機制—HandlerAndroid
- Android 之訊息機制Android
- Android Handler機制之ThreadLocalAndroidthread
- Android類裝載機制Android
- android IPC 通訊(上)-sharedUserId&&MessengerAndroidMessenger
- Android 訊息機制詳解(Android P)Android
- 藉助 AIDL 理解 Android Binder 機制——AIDL 的使用和原理分析AIAndroid
- Android10_原理機制系列_事件傳遞機制Android事件
- electron-ipc通訊效能分析
- View事件機制分析View事件
- Mysql鎖機制分析MySql
- Android事件分發:從原始碼角度分析View事件分發機制Android事件原始碼View
- Android 高階面試-2:IPC 相關Android面試