最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

Android 應(yīng)用工程師的 Binder 原理剖析(一)享學(xué)課堂全面介紹

2023-06-13 10:10 作者:享學(xué)課堂online  | 我要投稿

1.binder的出現(xiàn)

對于享學(xué)課堂Alvin老師關(guān)于Android 的Binder的介紹`是`Android`中最重要的一種進(jìn)程間通信機(jī)制,基于開源的`OpenBinder

George Hoffman當(dāng)時任Be公司的工程師,他啟動了一個名為OpenBinder的項(xiàng)目,在Be公司被ParmSource公司收購后,OpenBinderDinnie Hackborn繼續(xù)開發(fā),后來成為管理ParmOS6 Cobalt OS的進(jìn)程的基礎(chǔ)。在Hackborn加入谷歌后,他在OpenBinder的基礎(chǔ)上開發(fā)出了Android Binder(以下簡稱Binder),用來完成Android的進(jìn)程通信。

2.為什么需要學(xué)習(xí)binder

作為一名Android開發(fā),我們每天都在和Binder打交道,雖然可能有的時候不會注意到,譬如:

  • startActivity的時候,會獲取AMS服務(wù),調(diào)用AMS服務(wù)的startActivity方法

  • startActivity傳遞的對象為什么需要序列化

  • bindService為什么回調(diào)的是一個Ibinder對象

  • 多進(jìn)程應(yīng)用,各個進(jìn)程之間如何通信

  • AIDL的使用

  • ...

它們都和Binder有著莫切關(guān)系,當(dāng)碰到上面的場景,或者一些疑難問題的時候,理解Binder機(jī)制是非常有必要的。我們知道 Android 應(yīng)用程序是由 Activity、Service、Broadcast Receiver 和 Content Provide 四大組件中的一個或者多個組成的。有時這些組件運(yùn)行在同一進(jìn)程,有時運(yùn)行在不同的進(jìn)程。這些進(jìn)程間的通信就依賴于 Binder IPC 機(jī)制。不僅如此,Android 系統(tǒng)對應(yīng)用層提供的各種服務(wù)如:ActivityManagerService、PackageManagerService 等都是基于 Binder IPC 機(jī)制來實(shí)現(xiàn)的。Binder 機(jī)制在 Android 中的位置非常重要,毫不夸張的說理解 Binder 是邁向 Android 高級工程的第一步。


3.為什么Android選擇Binder

Android 系統(tǒng)是基于 Linux 內(nèi)核的,Linux 已經(jīng)提供了管道、消息隊(duì)列、共享內(nèi)存和 Socket 等 IPC 機(jī)制。那為什么 Android 還要提供 Binder 來實(shí)現(xiàn) IPC 呢?主要是基于性能、穩(wěn)定性和安全性幾方面的原因。

3.1 常見進(jìn)程間通信

共享內(nèi)存

共享內(nèi)存是進(jìn)程間通信中最簡單的方式之一,共享內(nèi)存允許兩個或更多進(jìn)程訪問同一塊內(nèi)存,當(dāng)一個進(jìn)程改變了這塊地址中的內(nèi)容的時候,其它進(jìn)程都會察覺到這個更改,它的原理如下圖所示:

因?yàn)楣蚕韮?nèi)存是訪問同一塊內(nèi)存,所以數(shù)據(jù)不需要進(jìn)行任何復(fù)制,是IPC幾種方式中最快,性能最好的方式。但相對應(yīng)的,共享內(nèi)存未提供同步機(jī)制,需要我們手動控制內(nèi)存間的互斥操作,較容易發(fā)生問題。同時共享內(nèi)存由于能任意的訪問和修改內(nèi)存中的數(shù)據(jù),如果有惡意程序去針對某個程序設(shè)計(jì)代碼,很可能導(dǎo)致隱私泄漏或者程序崩潰,所以安全性較差。

管道

管道分為命名管道和無名管道,它是以一種特殊的文件作為中間介質(zhì),我們稱為管道文件,它具有固定的讀端和寫端,寫進(jìn)程通過寫段向管道文件里寫入數(shù)據(jù),讀進(jìn)程通過讀段從讀進(jìn)程中讀出數(shù)據(jù),構(gòu)成一條數(shù)據(jù)傳遞的流水線,它的原理如下圖所示:

管道一次通信需要經(jīng)歷2次數(shù)據(jù)復(fù)制(進(jìn)程A -> 管道文件,管道文件 -> 進(jìn)程B)。管道的讀寫分阻塞和非阻塞,管道創(chuàng)建會分配一個緩沖區(qū),而這個緩沖區(qū)是有限的,如果傳輸?shù)臄?shù)據(jù)大小超過緩沖區(qū)上限,或者在阻塞模式下沒有安排好數(shù)據(jù)的讀寫,會出現(xiàn)阻塞的情況。管道所傳送的是無格式字節(jié)流,這就要求管道的讀出方和寫入方必須事先約定好數(shù)據(jù)的格式。

消息隊(duì)列

消息隊(duì)列是存放在內(nèi)核中的消息鏈表,每個消息隊(duì)列由消息隊(duì)列標(biāo)識符表示。消息隊(duì)列允許多個進(jìn)程同時讀寫消息,發(fā)送方與接收方要約定好,消息體的數(shù)據(jù)類型與大小。消息隊(duì)列克服了信號承載信息量少、管道只能承載無格式字節(jié)流等缺點(diǎn),消息隊(duì)列一次通信同樣需要經(jīng)歷2次數(shù)據(jù)復(fù)制(進(jìn)程A -> 消息隊(duì)列,消息隊(duì)列 -> 進(jìn)程B),它的原理如下圖所示:


Socket

Socket原本是為了網(wǎng)絡(luò)設(shè)計(jì)的,但也可以通過本地回環(huán)地址 (127.0.0.1) 進(jìn)行進(jìn)程間通信,后來在Socket的框架上更是發(fā)展出一種IPC機(jī)制,名叫UNIX Domain Socket。Socket是一種典型的C/S架構(gòu),一個Socket會擁有兩個緩沖區(qū),一讀一寫,由于發(fā)送/接收消息需要將一個Socket緩沖區(qū)中的內(nèi)容拷貝至另一個Socket緩沖區(qū),所以Socket一次通信也是需要經(jīng)歷2次數(shù)據(jù)復(fù)制,它的原理如下圖所示:

Binder

跨進(jìn)程通信是需要內(nèi)核空間做支持的。傳統(tǒng)的 IPC 機(jī)制如管道、Socket 都是內(nèi)核的一部分,因此通過內(nèi)核支持來實(shí)現(xiàn)進(jìn)程間通信自然是沒問題的。但是 Binder 并不是 Linux 系統(tǒng)內(nèi)核的一部分,那怎么辦呢?這就得益于 Linux 的動態(tài)內(nèi)核可加載模塊(Loadable Kernel Module,LKM)的機(jī)制;模塊是具有獨(dú)立功能的程序,它可以被單獨(dú)編譯,但是不能獨(dú)立運(yùn)行。它在運(yùn)行時被鏈接到內(nèi)核作為內(nèi)核的一部分運(yùn)行。這樣,Android 系統(tǒng)就可以通過動態(tài)添加一個內(nèi)核模塊運(yùn)行在內(nèi)核空間,用戶進(jìn)程之間通過這個內(nèi)核模塊作為橋梁來實(shí)現(xiàn)通信。

在 Android 系統(tǒng)中,這個運(yùn)行在內(nèi)核空間,負(fù)責(zé)各個用戶進(jìn)程通過 Binder 實(shí)現(xiàn)通信的內(nèi)核模塊就叫 Binder驅(qū)動(Binder Dirver)。

那么在 Android 系統(tǒng)中用戶進(jìn)程之間是如何通過這個內(nèi)核模塊(Binder 驅(qū)動)來實(shí)現(xiàn)通信的呢?難道是和前面說的傳統(tǒng) IPC 機(jī)制一樣,先將數(shù)據(jù)從發(fā)送方進(jìn)程拷貝到內(nèi)核緩存區(qū),然后再將數(shù)據(jù)從內(nèi)核緩存區(qū)拷貝到接收方進(jìn)程,通過兩次拷貝來實(shí)現(xiàn)嗎?顯然不是,否則也不會有開篇所說的 Binder 在性能方面的優(yōu)勢了。

這就不得不通道 Linux 下的另一個概念:內(nèi)存映射。

Binder IPC 機(jī)制中涉及到的內(nèi)存映射通過 mmap() 來實(shí)現(xiàn),mmap() 是操作系統(tǒng)中一種內(nèi)存映射的方法。內(nèi)存映射簡單的講就是將用戶空間的一塊內(nèi)存區(qū)域映射到內(nèi)核空間。映射關(guān)系建立后,用戶對這塊內(nèi)存區(qū)域的修改可以直接反應(yīng)到內(nèi)核空間;反之內(nèi)核空間對這段區(qū)域的修改也能直接反應(yīng)到用戶空間。

內(nèi)存映射能減少數(shù)據(jù)拷貝次數(shù),實(shí)現(xiàn)用戶空間和內(nèi)核空間的高效互動。兩個空間各自的修改能直接反映在映射的內(nèi)存區(qū)域,從而被對方空間及時感知。也正因?yàn)槿绱?,?nèi)存映射能夠提供對進(jìn)程間通信的支持。

Binder IPC 正是基于內(nèi)存映射(mmap)來實(shí)現(xiàn)的,但是 mmap() 通常是用在有物理介質(zhì)的文件系統(tǒng)上的。

比如進(jìn)程中的用戶區(qū)域是不能直接和物理設(shè)備打交道的,如果想要把磁盤上的數(shù)據(jù)讀取到進(jìn)程的用戶區(qū)域,需要兩次拷貝(磁盤-->內(nèi)核空間-->用戶空間);通常在這種場景下 mmap() 就能發(fā)揮作用,通過在物理介質(zhì)和用戶空間之間建立映射,減少數(shù)據(jù)的拷貝次數(shù),用內(nèi)存讀寫取代I/O讀寫,提高文件讀取效率。

而 Binder 并不存在物理介質(zhì),因此 Binder 驅(qū)動使用 mmap() 并不是為了在物理介質(zhì)和用戶空間之間建立映射,而是用來在內(nèi)核空間創(chuàng)建數(shù)據(jù)接收的緩存空間。

一次完整的 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ū)接收進(jìn)程用戶空間地址的映射關(guān)系;

  3. 發(fā)送方進(jìn)程通過系統(tǒng)調(diào)用 copyfromuser() 將數(shù)據(jù) copy 到內(nèi)核中的內(nèi)核緩存區(qū),由于內(nèi)核緩存區(qū)和接收進(jìn)程的用戶空間存在內(nèi)存映射,因此也就相當(dāng)于把數(shù)據(jù)發(fā)送到了接收進(jìn)程的用戶空間,這樣便完成了一次進(jìn)程間的通信。

如下圖:

小結(jié)

性能

首先說說性能上的優(yōu)勢。Socket 作為一款通用接口,其傳輸效率低,開銷大,主要用在跨網(wǎng)絡(luò)的進(jìn)程間通信和本機(jī)上進(jìn)程間的低速通信。消息隊(duì)列和管道采用存儲-轉(zhuǎn)發(fā)方式,即數(shù)據(jù)先從發(fā)送方緩存區(qū)拷貝到內(nèi)核開辟的緩存區(qū)中,然后再從內(nèi)核緩存區(qū)拷貝到接收方緩存區(qū),至少有兩次拷貝過程。共享內(nèi)存雖然無需拷貝,但控制復(fù)雜,難以使用。Binder 只需要一次數(shù)據(jù)拷貝,性能上僅次于共享內(nèi)存。

穩(wěn)定性

再說說穩(wěn)定性,Binder 基于 C/S 架構(gòu),客戶端(Client)有什么需求就丟給服務(wù)端(Server)去完成,架構(gòu)清晰、職責(zé)明確又相互獨(dú)立,自然穩(wěn)定性更好。共享內(nèi)存雖然無需拷貝,但是控制負(fù)責(zé),難以使用。從穩(wěn)定性的角度講,Binder 機(jī)制是優(yōu)于內(nèi)存共享的。

安全性

另一方面就是安全性。Android 作為一個開放性的平臺,市場上有各類海量的應(yīng)用供用戶選擇安裝,因此安全性對于 Android 平臺而言極其重要。作為用戶當(dāng)然不希望我們下載的 APP 偷偷讀取我的通信錄,上傳我的隱私數(shù)據(jù),后臺偷跑流量、消耗手機(jī)電量。傳統(tǒng)的 IPC 沒有任何安全措施,完全依賴上層協(xié)議來確保。首先傳統(tǒng)的 IPC 接收方無法獲得對方可靠的進(jìn)程用戶ID/進(jìn)程ID(UID/PID),從而無法鑒別對方身份。Android 為每個安裝好的 APP 分配了自己的 UID,故而進(jìn)程的 UID 是鑒別進(jìn)程身份的重要標(biāo)志。傳統(tǒng)的 IPC 只能由用戶在數(shù)據(jù)包中填入 UID/PID,但這樣不可靠,容易被惡意程序利用??煽康纳矸輼?biāo)識只有由 IPC 機(jī)制在內(nèi)核中添加。其次傳統(tǒng)的 IPC 訪問接入點(diǎn)是開放的,只要知道這些接入點(diǎn)的程序都可以和對端建立連接,不管怎樣都無法阻止惡意程序通過猜測接收方地址獲得連接。同時 Binder 既支持實(shí)名 Binder,又支持匿名 Binder,安全性高。

基于上述原因,Android 需要建立一套新的 IPC 機(jī)制來滿足系統(tǒng)對穩(wěn)定性、傳輸性能和安全性方面的要求,這就是 Binder

4.Binder架構(gòu)

Binder 是基于 C/S 架構(gòu)的。由一系列的組件組成,包括 Client、Server、ServiceManager、Binder 驅(qū)動。其中 Client、Server、Service Manager 運(yùn)行在用戶空間,Binder 驅(qū)動運(yùn)行在內(nèi)核空間。其中 Service Manager 和 Binder 驅(qū)動由系統(tǒng)提供,而 Client、Server 由應(yīng)用程序來實(shí)現(xiàn)。Client、Server 和 ServiceManager 均是通過系統(tǒng)調(diào)用 open、mmap 和 ioctl 來訪問設(shè)備文件 /dev/binder,從而實(shí)現(xiàn)與 Binder 驅(qū)動的交互來間接的實(shí)現(xiàn)跨進(jìn)程通信。

Client、Server、ServiceManager、Binder 驅(qū)動這幾個組件在通信過程中扮演的角色就如同互聯(lián)網(wǎng)中服務(wù)器(Server)、客戶端(Client)、DNS域名服務(wù)器(ServiceManager)以及路由器(Binder 驅(qū)動)之前的關(guān)系。

Client 先去ServiceManager中拿到Server的binder(BpBinder),然后Client再通過這個binder來“調(diào)用”Server端的代碼。當(dāng)然這個“調(diào)用”是跨進(jìn)程的過程,需要通過ioctl來支持,也就是需要Binder驅(qū)動支持。具體的流程如下圖所示。

5.總結(jié)

上面章節(jié)就是享學(xué)課堂Alvin老師的整體分析了一下IPC通信,那么很多關(guān)于binder通信的細(xì)節(jié),可能大家還會比較懵逼,那么這些不熟悉的或者大家懵逼的理論,我們將在接下來的內(nèi)容里面進(jìn)行分析。


Android 應(yīng)用工程師的 Binder 原理剖析(一)享學(xué)課堂全面介紹的評論 (共 條)

分享到微博請遵守國家法律
溧阳市| 黄平县| 泸溪县| 金阳县| 灵石县| 镇康县| 永吉县| 二手房| 合阳县| 多伦县| 玉门市| 黄陵县| 喀喇沁旗| 珠海市| 泰宁县| 乌海市| 台中市| 谷城县| 新郑市| 海林市| 伊宁县| 河北省| 静海县| 杭锦旗| 廉江市| 肇庆市| 平南县| 乐业县| 临沭县| 高雄市| 阳朔县| 慈利县| 万载县| 仪征市| 土默特左旗| 三门县| 卓尼县| 西贡区| 朝阳县| 瑞金市| 海宁市|