亚洲全黄无码一级在线看_国产剧情久久久性色_无码av一区二区三区无码_亚洲成a×人片在线观看

當前位置: 首頁 > 科技新聞 >

從 Android 6.0 源碼的角度剖析 Binder 工作原理 | C

時間:2019-11-13 09:20來源:網(wǎng)絡(luò)整理 瀏覽:
在從Android6.0源碼的角度剖析Activity的啟動過程一文(https://blog.csdn.net/AndrExpert/ar

在從Android 6.0源碼的角度剖析Activity的啟動過程一文(https://blog.csdn.net/AndrExpert/article/details/81488503)中,我們了解到Activity的啟動過程最終由系統(tǒng)服務(wù)ActivityManagerService完成,ActivityManagerServer是繼承于Binder且運行在系統(tǒng)進程中,Activity的啟動實質(zhì)是一次基于Binder機制的跨進程通信。除此之外,Android系統(tǒng)還為應(yīng)用程序提供了各種系統(tǒng)服務(wù),比如多媒體播放、音視頻獲取、讀取傳感器數(shù)據(jù)等,它們之間的交互都是由Binder機制實現(xiàn)的。那么,所謂的Binder究竟是什么?實際上,Binder并不是一個確切的概念,它在不同的層次表述大不相同,比如通常意義下,Binder指Android系統(tǒng)中特有的一種跨進程通信方式;從用戶空間的角度來說,對于Server進程,Binder指Binder本地對象,而對于Client進程,Binder指Binder代理對象;從內(nèi)核空間的角度來說,Binder指Binder驅(qū)動;從傳輸通信的角度來說,Binder是可以跨進程傳遞的對象。

作者 | 蔣東國

責編 | 屠敏

出品 | CSDN博客

Binder基本原理

IPC與Binder簡介

進程是程序的實體,它是程序的一次運行活動,同時也是操作系統(tǒng)資源分配和調(diào)度的基本單位。在操作系統(tǒng)中運行著許許多多的進程,為了保證系統(tǒng)的有序運行和進程間互不干擾,操作系統(tǒng)引入了進程隔離的概念來確保不同進程之間相互獨立。進程隔離使用了虛擬地址空間技術(shù),該技術(shù)通過為不同的進程分配不同的虛擬地址,使得對于每個進程來說都以為自己獨享了整個系統(tǒng),完全不知道其他進程的存在,這樣就避免了進程間錯誤的相互寫入數(shù)據(jù)而導(dǎo)致進程無法正常運行。然而,雖然進程隔離能夠確保每個進程的數(shù)據(jù)安全,不被惡意破壞,但畢竟操作系統(tǒng)是一個有機的的統(tǒng)一整體,就像人體樣,雖然人體的各個器官也是相互獨立,但是若要完成某一個行為,就需要在大腦的控制下對相關(guān)器官進行調(diào)配,同時器官之間也會相互傳遞信號,操作系統(tǒng)亦是如此。操作系統(tǒng)是管理計算機硬件與軟件資源的計算機程序,它由內(nèi)核、驅(qū)動程序、接口庫及外圍組成,其中,內(nèi)核是操作系統(tǒng)的核心,擁有訪問受保護的內(nèi)存空間和訪問底層硬件設(shè)備的所有權(quán)限。當操作系統(tǒng)需要執(zhí)行某個任務(wù)時,必然需要系統(tǒng)中相關(guān)進程在內(nèi)核的控制下進行協(xié)作,既然是相互協(xié)作,就必然牽涉到進程間的數(shù)據(jù)交互,為了實現(xiàn)這個目的,跨進程通信技術(shù)開始"閃亮登場"。

IPC,跨進程通信

跨進程通信(IPC,Interprocess Communication)是一組編程接口,它允許在一個操作系統(tǒng)中不同進程之間傳遞或交換信息,其存儲-轉(zhuǎn)發(fā)方式通信過程大致為:假設(shè)有兩個運行在用戶空間的進程A、B,進程A要給進程B發(fā)送數(shù)據(jù),那么進程A會通過系統(tǒng)調(diào)用copy_from_user將數(shù)據(jù)copy到內(nèi)核空間,然后把內(nèi)核空間通過系統(tǒng)調(diào)用copy_to_user將對應(yīng)的數(shù)據(jù)copy到進程B即完成。下圖為IPC通信模型:

用戶空間和內(nèi)核空間是人們從邏輯上抽離出來的概念,旨在區(qū)分操作系統(tǒng)中普通的應(yīng)用程序和內(nèi)核。內(nèi)核是操作系統(tǒng)的核心,它擁有訪問受保護內(nèi)存空間和底層硬件設(shè)備的所有權(quán)限,維持著整個操作系統(tǒng)的正常運行。為了保護內(nèi)核不受破壞,普通的應(yīng)用程序被授予有限的資源訪問權(quán)限,如果普通的應(yīng)用程序需要訪問受限的資源,就需要通過系統(tǒng)調(diào)用通過內(nèi)核來訪問這些被保護的資源。用戶空間訪問內(nèi)核空間通過系統(tǒng)調(diào)用實現(xiàn),用戶空間訪問用戶空間則需要通過內(nèi)核模塊/驅(qū)動來實現(xiàn)。

Android系統(tǒng)是基于Linux內(nèi)核實現(xiàn)的,自然支持Linux系統(tǒng)中的IPC方式,這些方式包括管道、System V IPC(包括消息隊列/共享內(nèi)存/信號燈)和socket。其中,管道是一種半雙工的通信方式,數(shù)據(jù)只能單向流通且只能在具有父子進程關(guān)系的進程間使用;System V IPC是Linux系統(tǒng)為了彌補管道在進程間通信的不足所引入,它包括消息隊列、信號燈和共享內(nèi)存三種進程間通信機制,它們共享通用的認證方式,即進程在使用某種類型的IPC資源以前,必須通過系統(tǒng)調(diào)用傳遞一個唯一的引用標識符到內(nèi)核來訪問這些資源;Socket套接字是一種通用的接口,用于跨網(wǎng)絡(luò)的進程間通信和本機上進程間的低速通信,并且支持Client-Server的通信方式。

下表為上述5種IPC方式區(qū)別:

(1) C/S結(jié)構(gòu):Client-Server結(jié)構(gòu)是一種網(wǎng)絡(luò)架構(gòu),它把客戶端與服務(wù)器區(qū)分開來。客戶端發(fā)送請求到服務(wù)器,服務(wù)器接收并處理請求,然后返回結(jié)果給客戶端。在Android系統(tǒng)中,大部分系統(tǒng)服務(wù)都是通過這種架構(gòu)為應(yīng)用程序提供服務(wù),從而讓應(yīng)用程序擁有豐富的功能。

(2) 存儲-轉(zhuǎn)發(fā)方式:數(shù)據(jù)先從發(fā)送方緩存區(qū)拷貝到內(nèi)核開辟的緩存區(qū)中,然后再從內(nèi)核緩存區(qū)拷貝到接收方緩存區(qū),因此整個過程需要拷貝兩次。

Binder簡介

雖然Android系統(tǒng)是基于Linux系統(tǒng)實現(xiàn)的,但它并沒有使用上述的5種方式作為系統(tǒng)的進程間通信方式,主要是由這幾種方式要么是開銷過大,要么就是安全性低。因為Android系統(tǒng)作為一種嵌入式系統(tǒng),設(shè)備資源相對有限,因此對相關(guān)的性能要求也非常高,過大的開銷會嚴重影響系統(tǒng)的運行性能。另外,Android系統(tǒng)是開放式的,擁有眾多的開發(fā)者平臺,應(yīng)用程序的來源也非常廣泛,同時傳統(tǒng)的IPC方式無法獲得對方進程可靠的UID/PID進行身份校驗,這會直接影響智能設(shè)備的安全。基于此,Android系統(tǒng)建立了一套新的IPC機制來滿足系統(tǒng)中對較高的傳輸性能和安全性通信要求,這種Android特有的IPC機制就是Binder機制。

Binder是基于OpenBinder實現(xiàn)的,OpenBinder由Google公司的Dianne Hackborn開發(fā),旨在提供一個簡單的進程間互相通訊的途徑。Binder機制采用C/S通信模型,它使用Binder來作為Server服務(wù)對外的訪問接入點和Client向Server發(fā)起服務(wù)請求的"地址",并且在進程間通信的過程中,數(shù)據(jù)傳輸只需拷貝一次,并且Client的身份驗證標志(UID/PID)只能由Binder機制在內(nèi)核中添加,因此具有安全性高、傳輸性能好等優(yōu)勢。與其他IPC機制不同,Binder使用了面向?qū)ο蟮乃枷雭砻枋鯯erver端的訪問接入點和Client端的服務(wù)請求發(fā)起地址,具體來說就是Server端的訪問接入點實質(zhì)是位于Server進程中的一個Binder實體對象,該對象提供了一套方法用于向Client端提供各種服務(wù);Client端的“地址”即為Binder實體對象的引用,Client將持有該引用向Server端發(fā)起服務(wù)請求。下圖為Binder機制的C/S模型:

雖說Binder機制的底層代碼由C實現(xiàn),但面向?qū)ο笏枷氲囊雽⑦M程間通信轉(zhuǎn)化為通過對某個Binder對象的引用并調(diào)用該對象的方法,而其獨特之處在于Binder對象是一個可以跨進程引用的對象,它的實體位于一個進程中,而它的引用卻遍布于系統(tǒng)的各個進程之中。

Binder通信框架

基于Binder機制的進程間通信,其通信框架主要涉及四個角色,即Server進程、Client進程、ServerManager進程以及Binder驅(qū)動,其中,Server、Client和ServerManager運行在用戶空間,Binder驅(qū)動運行在內(nèi)核空間。Binder驅(qū)動是Binder通信框架的核心,它工作于內(nèi)核空間,主要負責進程間Binder通信的建立、Binder在進程之間的傳遞、Binder引用計數(shù)管理以及數(shù)據(jù)包在進程之間的傳遞和交互等一系列底層支持;Server進程用于向Client進程提供遠程服務(wù),該進程會創(chuàng)建一個Binder實體(對象),并為其取一個字符串形式的名字,當該Binder實體被Binder驅(qū)動在ServerManger進行實名注冊后,我們又稱這個Binder實體為“實名Binder”,它將擔負起向Client提供具體的遠程服務(wù);Client進程即為我們的APP,它將通過遠程Binder實體的引用訪問遠程Server,獲取相關(guān)的服務(wù),這里為什么不是直接通過Binder實體訪問,我們在后面的Binder機制原理再詳述;ServerManager是一個系統(tǒng)進程,它管理著一張“查詢表”,該表記錄了Server進程中Binder實體名字到Client中對該Binder實體引用的對應(yīng)關(guān)系,以便使Client能夠通過Binder名字獲得對Server中Binder實體的引用。Binder通信框架結(jié)構(gòu)圖如下:

在Binder機制通信模型中,Server、Client、ServerManager以及Binder驅(qū)動的關(guān)系有點類似于互聯(lián)網(wǎng),它們分別對應(yīng)于互聯(lián)網(wǎng)中的服務(wù)器、客戶端、域名服務(wù)器(DNS)以及路由器,其中,服務(wù)器用于向客戶端提供服務(wù)且對外接入點為IP地址;客戶端用于向服務(wù)器發(fā)起請求服務(wù),且發(fā)起"地址"通常為域名;域名服務(wù)器提供遠程服務(wù)器的IP地址與其域名映射關(guān)系,便于客戶端能夠通過域名直接訪問服務(wù)器;路由器用于網(wǎng)絡(luò)管理、數(shù)據(jù)處理等,是互聯(lián)網(wǎng)絡(luò)的樞紐。Binder通信框架流程圖如下:

大致過程為:

首先,系統(tǒng)中某個進程向Binder驅(qū)動發(fā)起申請為ServerManager進程,該進程將建立一張系統(tǒng)中相關(guān)Server進程“名字”及其“地址”的映射表(查詢表); 其次,Server進程將自己“名字”和“地址”添加到ServerManager進程的查詢表中; 最后,Client進程從ServerManager進程獲取到遠程Server進程的真實“地址”,即建立Binder通信完畢。

Binder機制原理

前面談?wù)摰酱蟛糠謧鹘y(tǒng)的IPC都是基于存儲-轉(zhuǎn)發(fā)的方式實現(xiàn)的,即進程A通過系統(tǒng)調(diào)用copy_from_user將數(shù)據(jù)從用戶空間拷貝到內(nèi)核空間,然后再通過系統(tǒng)調(diào)用copy_to_user將數(shù)據(jù)拷貝從內(nèi)核空間拷貝到進程B,整個通信過程數(shù)據(jù)需要拷貝2次。但是Binder機制卻不是這么做的,而是把所有的工作均交給Binder驅(qū)動來完成,并且Binder本質(zhì)上只是一種底層通信方式和具體服務(wù)沒有關(guān)系。為了提供具體服務(wù)(或稱能力),Server必須提供一套接口函數(shù)以便Client通過遠程訪問使用各種服務(wù),這里使用代理(Proxy)模式來實現(xiàn),即**將接口函數(shù)定義在一個抽象類中,Server和Client均以該抽象類為基類實現(xiàn)所有的接口函數(shù),其中Server端是真正的功能實現(xiàn)并為每個函數(shù)進行一一編號以便Client精準調(diào)用,而Client端則是對這些函數(shù)遠程調(diào)用請求的包裝。此外,Server端還定義了一個Binder抽象類來處理來自Client的Binder請求數(shù)據(jù)包,其中最重要的成員函數(shù)是虛函數(shù)onTransact,該函數(shù)將用于分析收到的數(shù)據(jù)包,調(diào)用相應(yīng)的接口函數(shù)處理請求,并將最終的調(diào)用結(jié)果返回給Client。整個通信過程都是在Binder驅(qū)動的控制下完成的,并且Binder在Server中的實體是通過采用繼承方式以接口類和Binder抽象類為基類構(gòu)建的。**接下來,我們借助Binder學(xué)習(xí)指南一文中的一張圖來詳細剖析下Binder機制通信過程,了解Binder驅(qū)動、ServerManager(SM)在整個通信過程中所起的作用。

為了深入理解基于Binder機制的進程間通信原理,這里假設(shè)Server進程中有個Object對象(即Binder實體),它提供一個add方法供遠程調(diào)用,Client進程將通過Binder機制的方式訪問Server進程中Object對象的add方法,具體的通信過程如下:

Server在SM中注冊實名Binder

在Server進程中有一個Object對象(即Binder實體,下述均以Binder實體描述),它提供一個add方法,為了Client能夠找到自己并與之通信,Server進程為Binder實體創(chuàng)建了一個字符形式的名字,然后再將Binder實體及其名字以數(shù)據(jù)包的形式通過Binder驅(qū)動發(fā)送給ServerManager進行注冊,其注冊過程為:

首先,Binder驅(qū)動接收到Server發(fā)過來的數(shù)據(jù)包后,會取出數(shù)據(jù)包中的Binder實體及其名字,并為該Binder實體創(chuàng)建位于內(nèi)核中的實體節(jié)點,并生成與其名字對應(yīng)的引用;

然后,Binder驅(qū)動將Binder的名字和新建的引用打包傳遞給ServerManager,ServerManager收到數(shù)據(jù)包后從中取出名字和引用填入一張查找表中,這張表就像一個“通訊錄”且是系統(tǒng)唯一的,它記錄了系統(tǒng)中各種Server的名字(Binder實體字符形式名字)和地址(Binder實體的引用),而被注冊的這個Binder實體也稱為實名Binder。

Client從SM獲得實名Binder的引用

Client進程要想訪問Server進程的Binder實體的add方法,會將要訪問Binder實體的名字以數(shù)據(jù)包的形式發(fā)送給Binder驅(qū)動,Binder驅(qū)動取出名字查詢ServerManager中的查詢表即可獲得Binder實體及其引用。但是Binder驅(qū)動并沒有將真正的Binder實體返回給Client,而是“照著”Binder實體的樣子仿造一個一模一樣的對象作為代理返回給Client,這個對象又被稱之為代理對象ProxyBinder,它持有Binder實體的引用,且擁有與Binder實體完全相同能力(即方法),只是這些能力只是個“空殼”,真正的具體實現(xiàn)還是在Server進程的Binder實體中。由于驅(qū)動返回的代理對象(ProxyBinder)與Server進程中的Binder實體如此相似,給人的感覺好像是直接把Server進程Binder實體(對象)傳遞到了Client進程,因此,我們可以說Binder對象是可以跨進程傳遞的對象,而實際上Binder對象并沒有傳遞,傳遞的僅僅是Binder對象的引用,它將通過代理對象來承載。也就是說,Server進程中Binder對象指Binder實體(也稱Binder本地對象),Client進程中Binder對象指的是Binder代理對象。在Binder對象進行跨進程傳遞的時候,Binder驅(qū)動會自動完成這兩種類型的轉(zhuǎn)換。

需要注意的是,Binder驅(qū)動返回一個Binder實體的代理對象給Client是基于Client與Server歸屬于不同進程而言的,如果Client和Server歸屬于同一個進程,Binder驅(qū)動將直接將Server進程的Binder實體返回給Client。由于本文主要是考慮Client與Server歸屬于不同進程情況,因此待Client獲得代理對象ProxyBinder的那一刻,基于Binder機制的Client與Server遠程通信鏈路建立完畢。

Client與Server跨進程通信

在Binder驅(qū)動返回一個Binder的代理對象給Client進程后,Client進程就可以通過該代理對象與遠程Server進程進行通信。Binder代理對象繼承了Server提供的公共接口類并實現(xiàn)公共函數(shù)(注:并不是真正的實現(xiàn),真正的實現(xiàn)在Server進程的Binder實體中),是對遠程函數(shù)調(diào)用的包裝。接下來,我們分析下Client訪問Server中方法通信過程:(1) Client進程首先會將函數(shù)參數(shù)和Binder實體的引用以數(shù)據(jù)包的形式進行打包,然后將數(shù)據(jù)包發(fā)送給Binder驅(qū)動向指定Server發(fā)送請求,此后Client進程進入掛起狀態(tài),以等待返回值;(2) Binder驅(qū)動收到Client進程發(fā)送過來的數(shù)據(jù)包后,取出Binder實體的引用,獲得目的Server并將其喚醒,再將數(shù)據(jù)包發(fā)送給它處理。這里需要提下的是,由于該引用本來就是Binder驅(qū)動創(chuàng)建并交給ServerManager注冊用的,因此Binder驅(qū)動自然很容易就能夠通過該引用找到能夠接收數(shù)據(jù)包的Server和獲得指向Binder實體對應(yīng)的內(nèi)存空間;(3) Server進程收到Binder驅(qū)動發(fā)送過來的Binder請求數(shù)據(jù)包后,Server進程會利用之前開辟好線程池中的線程來處理該請求,通過調(diào)用Binder實體中的onTransact函數(shù),對收到的數(shù)據(jù)包進行分析,即取出數(shù)據(jù)包中請求的函數(shù)接口編碼,case-by-case地解析code值,待解析成功后,再從數(shù)據(jù)包中取出函數(shù)參數(shù)并調(diào)用相應(yīng)的接口函數(shù)處理請求,然后Server進程會將調(diào)用結(jié)果發(fā)送給Binder驅(qū)動;(4) Binder驅(qū)動收到Server進程返回的調(diào)用結(jié)果后,就會喚醒處于等待中的Client進程,并將結(jié)果返回給它,至此,一次跨進程通信完畢。

Java層Binder框架解析

在Android系統(tǒng)中,Binder框架由C/C++底層和Java上層構(gòu)成,其中C/C++底層提供功能實現(xiàn),Java上層為應(yīng)用進程間的通信提供接口。由于C/C++層底層實現(xiàn)極其復(fù)雜,本文暫不涉及這部分內(nèi)容,本節(jié)將詳細剖析Java層部分。根據(jù)Binder機制原理,Binder框架Java層部分主要包含四部分,即公共接口(IIterface)、Binder接口(IBinder)、Binder實體(或稱Binder本地對象)以及Binder代理對象(BinderProxy),它們各自的作用如下:

IIterface

IIterface是Android提供的一個接口,它表明遠程Server對象具有什么樣的能力,可理解為Server和Client契約,Binder本地對象和Binder代理對象均需實現(xiàn)該接口。Interface接口中只包含一個asBinder方法,該方法用于返回與該IInterface綁定的Binder本地對象。IIterface源碼如下:

publicinterfaceIInterface

{

// 返回與該IIterface綁定的Binder實體對象

publicIBinder asBinder();

}

IBinder

代表了一種跨進程傳輸?shù)哪芰?,實現(xiàn)該接口就能將這個對象進行跨進程傳遞,IBinder負責數(shù)據(jù)傳遞。在跨進程數(shù)據(jù)流經(jīng)驅(qū)動的時候,驅(qū)動會識別IBinder類型的數(shù)據(jù),從而自動完成不同進程Binder本地對象以及Binder代理對象的轉(zhuǎn)換。

publicinterfaceIBinder{

// 代碼省略

...

// 返回綁定在該Binder對象的IInterface有關(guān)的描述

public@NullableString getInterfaceDeorthrowsRemoteException;

// 判斷Binder通信鏈路是否斷開

publicbooleanisBinderAlive;

// 獲取deor對應(yīng)的本地IIterface,如果返回為空,說明

// Client和Server歸屬于不同進程

public@NullableIInterface queryLocalInterface(@NonNull String deor);

// 代碼省略

...

// 處理Binder請求

// code:要執(zhí)行的函數(shù)編碼

// data:函數(shù)參數(shù)

// reply:返回值

// flags:附加標志,暫時忽略

publicbooleantransact(intcode, @NonNull Parcel data, @Nullable Parcel reply,

intflags)throwsRemoteException;

// Binder鏈接死亡(斷開)回調(diào)接口

publicinterfaceDeathRecipient{

publicvoidbinderDied;

}

// 注冊Binder鏈接斷開通知

// 即當Binder鏈接斷開時,DeathRecipient接口的binderDied方法會被回調(diào)

publicvoidlinkToDeath(@NonNull DeathRecipient recipient, intflags)

throwsRemoteException;

// 移除已注冊的Binder鏈接斷開通知

publicbooleanunlinkToDeath(@NonNull DeathRecipient recipient, intflags);

}

Binder

Binder實體對象,位于Server進程中,它繼承了IBinder,從而具有跨進程傳輸?shù)哪芰?,但在實際通信過程中,Binder實體對象并沒有傳輸,傳輸?shù)闹皇窃搶ο蟮囊谩?/span>

Binder代理對象

遠程進程Binder對象的代理,位于Client進程中,它持有IBinder引用,也可以理解擁有跨進程傳輸?shù)哪芰Α?/span>

AIDL工作原理

AIDL(Android Interface Definition Language),即Android接口定義語言,是Android系統(tǒng)為了便于開發(fā)具備跨進程通信的應(yīng)用,專門提供的且用于自動生成Java層Binder通信框架的技術(shù)。AIDL的使用比較簡單,我們只需要編寫符合AIDL開發(fā)規(guī)范的源碼文件,AS就會自動生成用于跨進程通信的相關(guān)文件。這里以Server端向Client提供"加法計算"服務(wù)(能力)為例,詳細剖析Java層Binder通信框架原理。

首先,我們在工程中創(chuàng)建一個以".aidl"為后綴的源文件,文件命名為IComputeInterface,并提供一個add方法;

packagecom.jiangdg.hellobinder;

interfaceIComputeInterface{

intadd(inta,intb);

}

其次,"Build->make project"工程后AS就會自動在"app/build/generated/…/com/jiangdg/hellobuilder"目錄生成一個名為IComputeInterface.java接口文件。代碼框架大致如下:

publicinterfaceIComputeInterfaceextendsandroid.os.IInterface{

// Binder實體

publicstaticabstractclassStubextendsandroid.os.Binderimplements

com.jiangdg.hellobinder.IComputeInterface{

...

// Binder實體的代理對象

privatestaticclassProxyimplements

com.jiangdg.hellobinder.IComputeInterface{

...

}

}

// 公共方法

publicintadd(inta, intb)throwsandroid.os.RemoteException;

}

從IComputeInterface.java源碼我們可以大致看出,它主要包含三部分,即接口IComputeInterface,靜態(tài)抽象類Stub、靜態(tài)類Proxy,并由此構(gòu)成Java層的Binder通信框架。接下來,我們就來分析它們之間有何關(guān)聯(lián)以及起到的作用是什么?

(1) IComputeInterface:公共接口

IComputeInterface繼承于接口IInterface,它包含一個add方法且拋出RemoteException異常,由此可知add方法應(yīng)該是一個被遠程訪問的方法。根據(jù)Binder機制原理,我們自然容易明白IComputeInterface接口就是一個“契約”接口,它表明Server端能夠像Client端提供哪些服務(wù),也是Binder機制中的代理訪問的實現(xiàn)基礎(chǔ),Server中的Binder實體和Client中的Binder實體的代理均需要實現(xiàn)它,其中,在Binder實體中為add方法真正的實現(xiàn),在Binder實體的代理對象中只是對add方法的遠程調(diào)用請求包裝,在接下來的分析中可以驗證這一點。

publicinterfaceIComputeInterfaceextendsandroid.os.IInterface{

publicintadd(inta, intb)throwsandroid.os.RemoteException;

}

(2) IComputeInterface.Stub:Binder本地對象

從 IComputeInterface的源碼可知,Stub是IComputeInterface的一個靜態(tài)抽象內(nèi)部類,但是這不是關(guān)鍵的,也僅是AIDL中的生成代碼的一種形式而已,真正重要的是Stub繼承了Binder類和IComputeInterface接口,而Binder又繼承于IBinder。根據(jù)Binder機制原理,我們就可以得出Stub就是位于Server端中的Binder實體或稱Binder本地對象,它的源碼如下:

publicstaticabstractclassStubextendsandroid.os.Binderimplements

com.jiangdg.hellobinder.IComputeInterface{

// 表明IComputeInterface是本地接口描述

privatestaticfinaljava.lang.String DEOR =

"com.jiangdg.hellobinder.IComputeInterface";

// 將Stub本身(即Binder實體對象)綁定到接口Interface

publicStub{

this.attachInterface( this, DEOR);

}

// 將Binder實體對象轉(zhuǎn)換為IInterface,即創(chuàng)建Binder實體的代理對象,如果需要的話

publicstaticcom.jiangdg.hellobinder. IComputeInterface

asInterface(android.os.IBinder obj){

if((obj== null)) {

returnnull;

}

android.os.IInterface iin = obj.queryLocalInterface(DEOR);

if(((iin!= null)&&(iin instanceofcom.jiangdg.hellobinder.IComputeInterface))){

return((com.jiangdg.hellobinder.IComputeInterface));

}

returnnewcom.jiangdg.hellobinder.IComputeInterface.Stub.Proxy(obj);

}

// 返回Binder實體對象本身

@Override

publicandroid.os. IBinder asBinder{

returnthis;

}

// 分析處理Binder請求數(shù)據(jù)包,根據(jù)code找到相應(yīng)的節(jié)點

// 調(diào)用相應(yīng)的方法處理請求

@Override

publicbooleanonTransact(intcode, android.os.Parcel data, android.os.Parcel reply, intflags)throwsandroid.os.RemoteException{

switch(code){

caseINTERFACE_TRANSACTION:

{

reply.writeString(DEOR);

returntrue;

}

caseTRANSACTION_add:

{

data.enforceInterface(DEOR);

int_arg0;

_arg0 = data.readInt;

int_arg1;

_arg1 = data.readInt;

int_result = this.add(_arg0, _arg1);

reply.writeNoException;

reply.writeInt(_result);

returntrue;

}

}

returnsuper.onTransact(code, data, reply, flags);

}

staticfinalintTRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);

}

接下來,我們著重分析下Stub類的工作原理,這里從asInterface方法入手,該方法主要的作用是判斷Binder驅(qū)動傳遞過來的Binder對象obj類型,來決定是否想需要返回Binder對象的代理對象Proxy,即調(diào)用obj的queryLocalInterface方法判斷傳入的DEOR(接口描述)是否與obj綁定的一致,如果一致,則表明Client與Server歸屬于同一個進程,直接將Binder本地對象返回給Client;如果不一致,則表明Client與Server不屬于同一個進程,就需要將obj作為參數(shù)實例化一個Binder本地對象的代理Proxy給Client。onTransact方法用于分析處理Binder驅(qū)動發(fā)來的請求數(shù)據(jù)包,如果Client與Server屬于同一個進程,當Client要訪問Server中的add方法時,onTransact就會被直接調(diào)用,不再經(jīng)歷代理調(diào)用步驟。

(3) IComputeInterface.Stub.Proxy

Proxy是Stub的一個靜態(tài)內(nèi)部類,同樣也不是關(guān)鍵的,僅是AIDL中的生成代碼的一種形式而已,真正重要的是Proxy繼承了IComputeInterface接口,并持有一個IBinder對象的引用。根據(jù)Binder機制原理,我們就可以得出Proxy就是位于Client端中的Binder本地對象的代理。從Proxy的源碼可知,它不僅持有遠程Binder實體的引用,還重寫了公共方法add,該方法將Client要訪問遠程方法的參數(shù)封裝在Parcel對象中,然后調(diào)用遠程Binder實體的transact方法發(fā)起跨進程調(diào)用。通過查看Android源碼可知,transact方法的實現(xiàn)位于native層,它最終調(diào)用talkwithDriver函數(shù)將請求參數(shù)打包交給Binder驅(qū)動,Binder驅(qū)動識別后,最終會調(diào)用遠程Server中Binder實體的onTransact方法,即Stub的onTransact方法進行處理。需要注意的是,在實際開發(fā)中,Stub中onTransact方法所調(diào)用的add方法將由我們自己實現(xiàn),待add執(zhí)行完畢會將結(jié)果填入Parcel中以便Binder驅(qū)動返回給Client。Proxy源碼如下:

privatestaticclassProxyimplementscom.jiangdg.hellobinder.IComputeInterface

{

// 遠程Binder實體對象

privateandroid.os.IBinder mRemote;

Proxy(android.os.IBinder remote){

mRemote = remote;

}

// 返回與代理對象對應(yīng)的Binder實體

@Override

publicandroid.os. IBinder asBinder{

returnmRemote;

}

publicjava.lang. String getInterfaceDeor{

returnDEOR;

}

// 對遠程調(diào)用的封裝

@Override

publicintadd(inta, intb)throwsandroid.os.RemoteException{

android.os.Parcel _data = android.os.Parcel.obtain;

android.os.Parcel _reply = android.os.Parcel.obtain;

int_result;

try{

_data.writeInterfaceToken(DEOR);

_data.writeInt(a);

_data.writeInt(b);

// 調(diào)用遠程Binder實體的transact方法

// 開始處理訪問請求

mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);

_reply.readException;

_result = _reply.readInt;

}

finally{

_reply.recycle;

_data.recycle;

}

return_result;

}

}

至此,關(guān)于對Binder機制的分析將告一段落,最后,我們采用Android Binder設(shè)計與實現(xiàn)中的一段原話為Binder機制作個總結(jié):Binder模糊了進程邊界,淡化了進程間通信過程,整個系統(tǒng)仿佛運行于同一個面向?qū)ο蟮某绦蛑?,形形色色的Binder對象及其星羅棋布的引用仿佛粘接各個應(yīng)用程序的膠水,這也是Binder在英文的原意。

版權(quán)聲明:本文為 CSDN 博主「無名之輩FTER」的原創(chuàng)文章。

?國產(chǎn)數(shù)據(jù)庫激蕩 40 年

推薦內(nèi)容