Android內幕:Binder驅動的原理和實現

2021-01-19 IT168

  【IT168技術】IT168移動頻道通過上一節Android的IPC機制-Binder的介紹,大家應該對Binder有了基本的認識了。任何上層應用程式接口和用戶操作都需要底層硬體設備驅動的支持,並為其提供各種操作接口。本節首先從Binder的驅動實現入手,分析其原理和它提供給用戶層使用的接口。

  一、Binder驅動的原理

  為了完成進程間通信,Binder採用了AIDL(Android Interface Definition Language)來描述進程間的接口。在實際的實現中,Binder是作為一個特殊的字符型設備而存在的,設備節點為/dev/binder,其實現遵循Linux設備驅動模型,實現代碼主要涉及以下文件:

  kernel/drivers/staging/binder.h

  kernel/drivers/staging/binder.c

  在其驅動的實現過程中,主要通過binder_ioctl函數與用戶空間的進程交換數據。BINDER_WRITE_READ用來讀寫數據,數據包中有一個cmd域用於區分不同的請求。binder_thread_write函數用於發送請求或返回結果,而binder_thread_read函數則用於讀取結果。在binder_thread_write函數中調用binder_transaction函數來轉發請求並返回結果。當收到請求時,binder_transaction函數會通過對象的handle找到對象所在的進程,如果handle為空,就認為對象是context_mgr,把請求發給context_mgr所在的進程。請求中所有的Binder對象全部放到一個RB樹中,最後把請求放到目標進程的隊列中,等待目標進程讀取。數據的解析工作放在binder_parse()中實現;關於如何生成context_mgr,內核中提供了BINDER_SET_CONTEXT_ MGR命令來完成此項功能。下面我們就來看看Binder驅動究竟是如何實現的。

  二、Binder驅動的實現

  上面我們已經對Binder驅動的原理進行了分析,在開始分析驅動的實現之前,我們還是通過一個例子來說明Binder在實際應用中應該如何運用,以及它能幫我們解決什麼樣的問題。這樣會更容易幫助大家理解Binder驅動的實現。比如,A進程如果要使用B進程的服務,B進程首先要註冊此服務,A進程通過Binder獲取該服務的hanlde,通過這個handle,A進程就可以使用該服務了。此外,你可以把handle理解成地址。A進程使用B進程的服務還意味著二者遵循相同的協議,這個協議反映在代碼上就是二者要實現IBinder接口。

  1.「對象」與「引用」

  Binder不僅是Android系統中的一個完善的IPC機制,它也可以被當作Android系統的一種RPC(遠程過程調用)機制,因為Binder的功能就是在本地「執行」其他進程的功能。因此,進程在通過Binder獲取將要調用的進程服務時,可以是一個本地對象,也可以是一個遠程服務的「引用」。這一點可能比較難以理解,稍候就會為大家分析,這裡就先記住Binder不僅可以與本地進程通信,還可以與遠程進程通信;這裡的本地進程就是我們所說的本地對象,而遠程進程則是我們所說的遠程服務的一個「引用」 。[1]

  Binder的實質就是要把對象從一個進程映射到另一個進程中,而不管這個對象是本地的還是遠程的。如果是本地對象,更好理解;如果是遠程對象,就按照我們上面所講的來理解,即將遠程對象的「引用」從一個進程映射到另一個進程中,於是當使用這個遠程對象時,實際上就是使用遠程對象在本地的一個「引用」,類似於把這個遠程對象當作一個本地對象在使用。這也就是Binder與其他IPC機制不同的地方。

  這個本地「對象」與遠程對象的「引用」有什麼不同呢?本地「對象」表示本地進程的地址空間的一個地址,而遠程對象的「引用」則是一個抽象的32位句柄。它們之間是互斥的:所有的進程本地對象都是本地進程的一個地址(address、ptr、binder),所有的遠程進程的對象的「引用」都是一個句柄。對於發送者進程來說,不管是「對象」還是「引用」,它都會認為被發送的Binder對象是一個遠程對象的句柄(即遠程對象的「引用」)。但是,當Binder對象的數據被發送到遠端接收進程時,遠端接收進程則會認為該Binder對象是一個本地對象地址(即本地對象)。正如我們之前說的,當Binder對象被接收進程接收後,不管該Binder對象是本地的還是遠程的,它都會被當作一個本地進程來處理。因此,從第三方的角度來說,儘管名稱不同,對於一次完整的Binder調用,都將指向同一個對象,Binder驅動則負責兩種不同名稱的對象的正確映射,這樣才能把數據發送給正確的進程進行通信。這個映射關係也是進程間引用對象的基礎,對一個對象的引用,在遠程是句柄,在本地則是地址(即本地對象的地址)。

  後續IT168移動頻道會介紹分析該機制中所使用的數據結構體,然後再對整個流程進行分析,敬請關注。

相關焦點

  • 技術內幕:Android的IPC機制-Binder
    Android同時為Java環境和C/C++環境提供了Binder機制。本章主要介紹C/C++環境下的Binder機制,主要包括Binder驅動的實現、運作原理、IPC機制的實現、接口等,所以本章可能會涉及部分系統運行庫的原始碼,我們將詳細講解。
  • 大廠愛考的 Binder 系統服務註冊問題怎麼破?
    BinderProxy和BpBinder分別在Jave Binder和Native Binder作為客戶端的代表,BpServiceManager通過BpBinder來實現通信、同樣的,ServiceManagerProxy也會將業務的請求交給BinderProxy來處理。
  • 面試進階之binder通信
    首先 Binder 驅動在內核空間創建一個數據接收緩存區;2. 接著在內核空間開闢一塊內核緩存區,用於接手發送進程發送的數據。3. 實現內存映射,內核緩存區和接收進程的用戶空間地址都映射到同一個接收緩存區。4. 發送進程通過系統調用 copy_from_user() 將數據 copy 到內核中的內核緩存區,這是唯一的一次數據copy。5.
  • 淺談Binder
    Binder通訊性能好,穩定性和安全性高。所有的IPC都是基於Linux內核實現的,Binder也不例外,Binder驅動就是整個Binder通訊的核心。那麼Binder驅動是如何實現進程間通訊的?並進行mmap操作,完成虛擬內存和物理內存的映射。當客戶端通過ioctl方法跟binder驅動通訊時,會封裝此次通訊的數據,目標handle就是數據之一,這個數據就是用來查找目標節點(服務端在binder驅動創建的binder節點)的關鍵。imagehandle的保存者---ServiceManager既然handle如此重要,那它是從哪來的?
  • 「Binder機制」實例篇,超詳細~
    橋梁搭好了,但是具體 aidl 的功能的實現還沒有做,下一步就要讓服務端完成這些功能的實現。Stub 抽象類即是我們 server 端要實現的類,即具體的 aidl 的功能需要 server 端實現 aidl 中的 Stub 抽象類才能具體化。
  • Android 沉浸式狀態欄的實現
    1、通過設置Theme主題來設置狀態欄和導航欄的透明度這裡,我們需要注意Android5.0(API21)以上的狀態欄,會有一層變透明的遮罩。;item name="android:statusBarColor">@android:color/transparent</item>    </style></resources>因為在5.0是半透明的,所以設置android:statusBarColor屬性為透明的即可效果圖如下
  • Android實現社交應用中的評論和回復功能
    好了,廢話不多說,下面讓我們來看看效果具體如何實現的吧。大家應該不難看出來,頁面整體採用了CoordinatorLayout來實現詳情頁的頂部視差效。同時,這裡我採用ExpandableListView來實現多級列表,然後再解決它們的嵌套滑動問題。OK,我們先從ExpandableListView開始動手。
  • Android側滑-RecyclerView輕鬆實現高效的側滑菜單
    二 知識準備ItemTouchHelper是Android系統提供的一個幫助類,可以很輕鬆的用它實現長按拖拽和側滑刪除功能(這裡的是側滑之後直接刪除整條Item),下面來看一下使用方法.:id="@+id/item_text"        android:layout_width="match_parent"        android:layout_height="50dp"        android:background="#e1e1e1"        android:gravity="center"        android
  • 電源供電以及電機驅動原理與電路分析
    電機驅動電路原理如圖2-1所示: 該上拉電阻除了提高驅動能力外,還有一個作用,就是進行電平轉換。經查,ULN2003的接口邏輯為:5V-TTL, 5V-CMOS邏輯。而在3.3V供電的情況下,I/O口可以提供3.3V-LVTTL,3.3V-LVCMOS,3.3V-PCI和SSTL-3接口邏輯電平。因此,需要外接5V的上拉電阻將I/O電平規格變成5V電平邏輯。
  • 初識Spring Cloud Stream,什麼是消息驅動微服務框架
    Spirng Cloud Stream 本質上就是整合了 Spring Boot 和 Spring Integration,實現一套輕量級的消息驅動的微服務框架。通過使用 Spring Cloud Stream 可以有效簡化開發人員對消息中間件的使用複雜度,讓系統開發人員可以有更多的精力關注於核心業務邏輯的處理。
  • android布局和界面 - CSDN
    在線性布局中的控制項允許有自己的margins和gravity屬性。    LinearLayout.LayoutParams用來定義針LinearLayout布局的專用屬性,它包括以下內容:1)android:layout_weight用於在LinearLayout中把所有子View排布之後的剩餘空間按照它們的layout_weight分配給各個擁有這個屬性的View。
  • 網絡嗅探器工作原理及驅動流程
    隨著計算機網絡應用的普及,和Windows網絡作業系統的廣泛應用,使得在Window下保障網絡通信安全成為一個迫切需要解決的問題。本文基於NDIS中間層驅動程序實現網絡嗅探器,為滿足上述需求提供了充分的可能。   網絡嗅探器的基本工作原理   網絡嗅探器利用的是共享式的網絡傳輸介質。共享即意味著網絡中的一臺機器可以嗅探到傳遞給本網段(衝突域)中的所有機器的報文。
  • Android一步一步剖析+實現仿支付寶手勢密碼自定義View
    最近項目需求:要求在項目中添加手勢密碼和指紋驗證,恰巧最近在苦練自定義View,於是參考了網上輪子和自己的理解,實現了如下的效果。
  • 單片機驅動蜂鳴器原理與設計
    蜂鳴器是一種一體化結構的電子訊響器,本文介紹如何用單片機驅動蜂鳴器,他廣泛應用於計算機、印表機、複印機、報警器、電話機等電子產品中作發聲器件。   蜂鳴器主要分為壓電式蜂鳴器和電磁式蜂鳴器兩種類型。
  • 蜂鳴器驅動電路圖解_有源蜂鳴器原理_有源蜂鳴器和無源蜂鳴器如何...
    打開APP 蜂鳴器驅動電路圖解_有源蜂鳴器原理_有源蜂鳴器和無源蜂鳴器如何區分 發表於 2017-08-25 09:12:49
  • 單片機驅動8×8點陣顯示屏硬體原理
    在驅動點陣時,雖然具有專用的點陣驅動晶片,如MAX7219,但是該晶片價格比較高,所以應用並沒有很普遍。而74HC595和74HC138的組合來驅動點陣應用卻非常廣泛。我在上學階段,給公司有償設計過戶外點陣屏,使用的就是74HC595和74HC138。下面就介紹這種方案。點陣的實物圖如下圖所示。
  • Android View進階之實現仿支付寶手勢密碼自定義View
    ,於是參考了網上輪子和自己的理解,實現了如下的效果。    (6)小View也同理 可以實現,需要注意的是 在手勢密碼第一次註冊的時候存在小View,在認證的時候無小view,我們可以根據狀態,在onDraw中設置隱藏。二、分析完後,我們就一步一步來實現吧:1、首先模板應該具有通用性與可定製性,我們需要定義一個attrs。
  • android 從後臺啟動頁面專題及常見問題 - CSDN
    OCRus支持三種語言的識別:英語、中文和日文。這三個Tesseract語言包合起來約有70M左右,APK文件中拷貝語言包到手機存儲中需要幾秒時間,所以我們做了一個啟動頁面,在為用戶展示App第一印象的同時,後臺拷貝這三個語言包。
  • Android實戰項目真槍實彈第二炮
    【正文】Android實戰項目真槍實彈第二炮    上節給大家講解了Android項目工具的使用和框架的搭建,本節咱們來完成每個項目都會有的引導頁的實現,動態加載圓點標記效果。具體實現的功能如下:    1.可以左右滑動圖片。
  • 教你如何在Mac系統下編譯Android系統的源碼
    「全國公廁雲平臺」11月19日上線試運行,匯總全國近33萬條公廁信息,初步實現快速尋廁功能。