欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android 圖文詳解Binder進程通信底層原理

 更新時間:2021年10月23日 10:40:30   作者:帥次  
Android系統(tǒng)中,多進程間的通信都是依賴于底層Binder IPC機制,Binder機制是一種RPC方案。例如:當進程A中的Activity與進程B中的Service通信時,就使用了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)文章

最新評論