Android 圖文詳解Binder進程通信底層原理
之前了解到進程與多進程,涉及多進程不可避免的遇到了進程間通信,說到進程間通信,Binder 成了一道繞不過的坎。接下來咱們逐一了解。
🔥 什么是進程間通信
進程間通信(IPC,Inner Process Comunication),就是指不同進程之間的信息傳遞。
進程是系統(tǒng)進行資源分配和調(diào)度的基本單位,是操作系統(tǒng)的結(jié)構(gòu)的基礎(chǔ);一個應(yīng)用至少有一個進程,一個進程中有包含了多個線程(線程是CPU調(diào)度的最小單位),進程相當于是線程的ViewGroup,線程相當于操作系統(tǒng)分配個進程的View。
🔥 什么是 Binder
Binder 是 Android 系統(tǒng)中進程間通信機制(IPC)的一種方式,它是這些進程間通訊的橋梁。正如其名"粘合劑"一樣,它把系統(tǒng)中各個組件粘合到了一起,是各個組件的橋梁。
應(yīng)用層:是一個能發(fā)起通信的Java類。
- Client:是對 Binder 代理對象,是 Binder 實體對象的一個遠程代理。
- Server:是 Server 中的 Binder 實體對象。
機制:是一種進程間通信機制。
驅(qū)動:是一個虛擬物理設(shè)備驅(qū)動;
如startActivity的簡圖:
這里就用到了 Binder 通信,你會發(fā)現(xiàn)這里還有 Socker 通信,那我為什么要用 Binder 而不用 Socket。
🔥 Android 中 IPC 的方式
名稱 | 特點 | 使用場景 |
---|---|---|
Bundle | 只能傳輸實現(xiàn)了序列化或者一些Android支持的特殊對象 | 適合用于四大組件之間的進程交互 |
文件 | 不能做到進程間的即時通信,并且不適合用于高并發(fā)的場景 | 適合用于SharedPreference以及IO操作 |
ContentProvider | 可以訪問較多的數(shù)據(jù),支持一對多的高并發(fā)訪問,因為ContentProvider已經(jīng)自動做好了關(guān)于并發(fā)的機制 | 適合用于一對多的數(shù)據(jù)共享并且需要對數(shù)據(jù)進行頻繁的CRUD操作 |
Socket | 通過網(wǎng)絡(luò)傳輸字節(jié)流,支持一對多的實時通信,但是實現(xiàn)起來比較復雜 | 適合用于網(wǎng)絡(luò)數(shù)據(jù)共享 |
Messenger | 底層原理是AIDL,只是對其做了封裝,但是不能很好的處理高并發(fā)的場景,并且傳輸?shù)臄?shù)據(jù)只能支持Bundle類型 | 多進程、單線程且線程安全 |
AIDL | 功能強大,使用Binder機制,支持一對多的高并發(fā)實時通信,但是需要處理好線程同步 | 一對多并且有遠程進程通信的場景 |
🔥 Binder 優(yōu)勢
出發(fā)點 | Binder | 共享內(nèi)存 | Socket |
---|---|---|---|
性能 | 拷貝一次 | 無需拷貝 | 拷貝兩次 |
特點 | 基于C/S架構(gòu),易用性高 | 控制復雜,易用性差 | 基于C/S架構(gòu),通用接口,傳輸效率低、開銷大 |
安全 | 每個APP分配UID,同時支持實名和匿名 | 依賴上層協(xié)議,訪問接入點是開放的不安全 | 依賴上層協(xié)議,訪問接入點是開放的不安全 |
通過以上對比,Android 最終選擇了自建一套兼顧好用、高效、安全的 Binder。
- 好用:基于C/S架構(gòu),易用性高
- 高效:用 mmap() 進行內(nèi)存映射,只需一次拷貝
- 安全強:每個 APP 分配UID(進程的身份證號),同時支持實名(系統(tǒng)服務(wù))和匿名(自己創(chuàng)建的服務(wù))
可以讓自己的服務(wù)前往 ServiceManager 注冊,注冊后實名。
🔥 Linux 傳統(tǒng)的 IPC 原理
了解 Linux IPC 相關(guān)的概念和原理有助于我們理解 Binder 通信原理。因此,在介紹 Binder 跨進程通信原理之前,我們先聊聊 Linux 系統(tǒng)下傳統(tǒng)的進程間通信是如何實現(xiàn)。
💥 基本概念
由上圖看出:
- 進程隔離。
- 進程空間劃分:用戶空間(User Space)/內(nèi)核空間(Kernel Space)。
- 系統(tǒng)調(diào)用:用戶態(tài)/內(nèi)核態(tài)。
🌀 進程隔離
操作系統(tǒng)中,進程與進程間內(nèi)存是不共享的。SCC 進程無法直接訪問 Service 進程的數(shù)據(jù)。SCC 進程和 Service 進程之間要進行數(shù)據(jù)交互就得采用進程間通信(IPC)。
🌀 進程空間劃分
現(xiàn)在操作系統(tǒng)都是采用的虛擬存儲器。操作系統(tǒng)的核心是內(nèi)核,獨立于普通的應(yīng)用程序,可以訪問受保護的內(nèi)存空間,也可以訪問底層硬件設(shè)備的權(quán)限。為了保護用戶進程不能直接操作內(nèi)核,保證內(nèi)核的安全,操作系統(tǒng)從邏輯上將虛擬空間劃分為用戶空間(User Space)和內(nèi)核空間(Kernel Space)。
- 內(nèi)核空間(Kernel Space):是系統(tǒng)內(nèi)核運行的空間;
- 用戶空間(User Space):是用戶程序運行的空間。
所有內(nèi)核空間(虛擬地址)都映射在同一塊物理內(nèi)存,這樣就實現(xiàn)了內(nèi)存共享(所有進程可通過IPC訪問)。
為了保證安全性,它們之間是隔離的。即使用戶程序蹦了,內(nèi)核也不受影響。
🌀 系統(tǒng)調(diào)用
進程內(nèi) 用戶空間 & 內(nèi)核空間 進行交互 需通過系統(tǒng)調(diào)用,主要通過函數(shù):
- copy_from_user():將用戶空間的數(shù)據(jù)拷貝到內(nèi)核空間;
- copy_to_user():將內(nèi)核空間的數(shù)據(jù)拷貝到用戶空間。
用戶態(tài):當進程在執(zhí)行用戶自己的代碼的時候,我們稱其處于用戶運行態(tài)(用戶態(tài));
內(nèi)核態(tài):當一個進程執(zhí)行系統(tǒng)調(diào)用而陷入內(nèi)核代碼中執(zhí)行時,稱進程處于內(nèi)核運行態(tài)(內(nèi)核態(tài))。
系統(tǒng)調(diào)用是用戶空間訪問內(nèi)核空間的唯一方式。
💥 傳統(tǒng) IPC 通信原理
如圖,這就是 Sokcet的拷貝兩次。
當然目前 Linux 已經(jīng)引入 Binder 通信機制。
🔥 Binder IPC原理
上面整了一堆 Linux 下的 IPC 相關(guān)概念及原理,接下來我們正式介紹下 Binder IPC 的原理。
💥 Binder 采用分層架構(gòu)設(shè)計
- 應(yīng)用層: 對于應(yīng)用通過調(diào)用startActivity()然后調(diào)用 AMP.startService , 經(jīng)過層層調(diào)用,最終必然會調(diào)用到AMS.startService。
- Framework: 客戶類BinderProxy和服務(wù)類Binder(Binder通信是采用C/S架構(gòu), Android系統(tǒng)的基礎(chǔ)架構(gòu)便已設(shè)計好Binder在Java )。
- Native層: 對于Native層,可以直接使用BpBinder和BBinder(當然這里還有JavaBBinder)即可, 對于上一層Framework 的通信也是基于這個層面。
- Kernel: 這里是Binder Driver, 前面3層都跑在用戶空間,對于用戶空間的內(nèi)存資源是不共享的,每個Android的進程只能運行在自己進程所擁有的虛擬地址空間, 而內(nèi)核空間卻是可共享的. 真正通信的核心環(huán)節(jié)還是在Binder Driver。
💥 Binder 驅(qū)動
在 Android 系統(tǒng)中,這個運行在內(nèi)核空間,負責各個用戶進程通過 Binder 實現(xiàn)通信的內(nèi)核模塊就叫 Binder 驅(qū)動(Binder Dirver)。
💥 Binder IPC 內(nèi)存映射
Binder IPC 正是基于內(nèi)存映射(mmap)來實現(xiàn)的,一次完整的 Binder IPC 通信過程通常是這樣:
1、Binder 驅(qū)動在內(nèi)核空間創(chuàng)建一個數(shù)據(jù)接收緩存區(qū);
2、在內(nèi)核空間開辟一塊內(nèi)核緩存區(qū),
- 建立內(nèi)核緩存區(qū)和內(nèi)核中數(shù)據(jù)接收緩存區(qū)之間的映射關(guān)系;
- 內(nèi)核中數(shù)據(jù)接收緩存區(qū)和接收進程用戶空間地址的映射關(guān)系;
3、發(fā)送數(shù)據(jù)完成了一次進程間的通信。
- 發(fā)送方進程通過系統(tǒng)調(diào)用 copy_from_user() 將數(shù)據(jù) 拷貝 到內(nèi)核中的內(nèi)核緩存區(qū);
- 由于內(nèi)核緩存區(qū)和數(shù)據(jù)接收緩存區(qū)存在內(nèi)存映射,因此也就相當于把數(shù)據(jù)發(fā)送到了數(shù)據(jù)接收緩存區(qū);
- 由于數(shù)據(jù)接收緩存區(qū)和進程的用戶空間存在內(nèi)存映射因此也就相當于把數(shù)據(jù)發(fā)送到了接收進程的用戶空間。
內(nèi)存映射能減少數(shù)據(jù)拷貝次數(shù),實現(xiàn)用戶空間和內(nèi)核空間的高效互動。兩個空間各自的修改能直接反映在映射的內(nèi)存區(qū)域,從而被對方空間及時感知。也正因為如此,內(nèi)存映射能夠提供對進程間通信的支持。
Binder傳值限制:
- 原來的 BINDER_VM_SIZE:
((1 * 1024 * 1024) - 4096 * 2)
- 現(xiàn)在的BINDER_VM_SIZE:
((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
sysconf(_SC_PAGE_SIZE)
:這個函數(shù)用來獲取系統(tǒng)執(zhí)行的配置信息。例如頁大小、最大頁數(shù)、cpu個數(shù)、打開句柄的最大個數(shù)等等。
這個值表示你Binder最多傳這么多,超出就失敗。
💥 Android Binder 原理圖
🌀 Bind 原理圖
Binder通信采用C/S架構(gòu),從組件視角來說,包含Client、Server、ServiceManager 以及 Binder 驅(qū)動,其中 ServiceManager 用于管理系統(tǒng)中的各種服務(wù)。
此處的ServiceManager是指Native層的ServiceManager(C++),并非指framework層的ServiceManager(Java) 原因:
所以,原理圖可表示為以下:
🌀 Bind 原理圖交互
Client、Server、ServiceManager屬于進程空間的用戶空間,不可進行進程間交互(下圖虛線表示)。
所以他們都通過與 Binder 驅(qū)動 進行交互的,從而實現(xiàn)IPC通信方式。
所以,原理圖可表示為以下:
🌀 Bind 原理圖交互路線
到這里 Binder 原理算是搞定了。不知道你懂了多少,有疑問可以聯(lián)系我,我們一起探討。下一篇咱們一起學習 Binder 在 Android 中的具體實現(xiàn)。
到此這篇關(guān)于Android 圖文詳解Binder進程通信底層原理的文章就介紹到這了,更多相關(guān)Android Binder內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Flutter?Widget之FutureBuilder使用示例詳解
這篇文章主要為大家介紹了Flutter?Widget之FutureBuilder使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-11-11Android開發(fā)中日期工具類DateUtil完整實例
這篇文章主要介紹了Android開發(fā)中日期工具類DateUtil,結(jié)合完整實例形式分析了Android針對日期與時間的計算、轉(zhuǎn)換、格式化、獲取等相關(guān)操作技巧,需要的朋友可以參考下2017-11-11kotlin object關(guān)鍵字單例模式實現(xiàn)示例詳解
這篇文章主要為大家介紹了kotlin object關(guān)鍵字單例模式實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-01-01Android使用CountDownTimer類實現(xiàn)倒計時鬧鐘
這篇文章主要為大家詳細介紹了Android使用CountDownTimer類實現(xiàn)倒計時鬧鐘,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-01-01Android MediaPlayer實現(xiàn)音樂播放器實例代碼
這篇文章主要介紹了Android MediaPlayer實現(xiàn)音樂播放器實例代碼的相關(guān)資料,需要的朋友可以參考下2017-01-01Android基礎(chǔ)控件(EditView、SeekBar等)的使用方法
這篇文章主要介紹了Android基礎(chǔ)控件的屬性及使用方法,介紹了基礎(chǔ)控件有TextView、ImageView、Button、EditView等,感興趣的小伙伴們可以參考一下2016-03-03Android?源碼淺析RecyclerView?Adapter
這篇文章主要介紹了Android?源碼淺析之RecyclerView?Adapter示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12