第三節-Android10.0 Binder通信原理(三)-ServiceManager篇

1、概述

????????在Android中,系統提供的服務被包裝成一個個系統級service,這些service往往會在設備啟動之時添加進Android系統,當某個應用想要調用系統某個服務的功能時,往往是向系統發出請求,調用該服務的外部接口。在上一節我們了解到,這種外部接口,我們通常稱之為代理接口,也就是我們要拿到目標服務對應的代理對象。
?? ?//TODO

?? ?在Android8.0后,谷歌引入Treble機制,binder機制增加了hwbinder和vndbinder,其中vndbinder的守護進程為vndservicemanager。
?? ?vndservicemanager和service共用同一份代碼,只是傳入的參數和宏控制的流程有部分差異。
?? ?vndservicemanager會傳入參數“/dev/vndbinder”,servicemanager使用默認的“/dev/binder”。
?? ?servicemanager主要做了以下幾件事:
?? ?1、打開binder驅動,申請了128k的內存空間
?? ?2、然后調用binder_become_context_manager()讓自己成為整個系統中唯一的上下文管理器,其實也就是service管理器
?? ?3、調用binder_loop()進入無限循環,不斷監聽并解析binder驅動發來的命令


2、Binder架構

//TODO

3、servicemanager的啟動

//TODO

4、service_manager調用棧:

//TODO

5、源碼分析

? ? 5.1 主程序啟動main()

?????????//TODO

? ? 5.2 binder_open()

? ? ? ? servicemanager啟動后,先通過binder_open()來打開“/dev/binder”,代碼如下:
?? ??? ?

binder_open()的工作也比較簡單,分為以下幾步:

1、通過系統調用open()來打開“/dev/binder”,獲得一個句柄信息,在Binder驅動重對應的是函數binder_open()

2、通過ioctl獲取binder的版本信息,比較binder協議版本是否相同,不同則跳出,在Binder驅動重對應的是函數binder_ioctl()

3、通過mmap內存映射128k的內存空間,即把binder驅動文件的128K字節映射到了內存空間,這128K內存空間的servicemanager使用,在Binder驅動重對應的是函數binder_mmap()。

其他的binder服務進程會映射BINDER_VM_SIZE((1*1024*1024)-sysconf(SC_PAGE_SIZE)*2)的內存空間,SC_PAGE_SIZE表示一個page頁的大小,通常情況下為4K,即(1M-4K*2)=(1M-7K)

這個page的大小,不同廠家有時候也會調整大小,一般有1M,64K,4K,1KB,通常為4K。

ServiceManager進程mmap的內存大小可以通過adb shell命令得出:

其中0x7457b61000 -0x745d41000=0x20000,轉成10進制,即為128K

ARM32內存映射:

虛擬空間的低3GB部分從0-0XBFFFFFFF的虛擬線性地址,用戶態和內核態都可以尋址,這部分也是每個進程的獨立空間。

虛擬空間的高1G部分從0XC00000000到0XFFFFFFFF的虛擬地址,只有內核態的進程才能訪問,這種限制由頁目錄和頁眉描述符的權限標示位決定,通過MML啟動控制

ARM64內存映射:

默認情況下,32位系統默認只能支持4G的內存,在打開PAE后,最大可以擴展到64G的內存,隨著物理硬件的不斷升級,現在的內存越來越大,因此基本上都切換到了64位系統。

理論上講,64位的地址總線可以支持高達16EB(2^64)的內存。

2^64次方太大了,Linux內核只采用了64bits的一部分(開啟CONFIG_ARM64_64K_PAGES時使用42bits,頁大小是4K時使用39bits),該文假設使用的頁大小是4K(VA_BITS=39)

ARM64有足夠的虛擬地址,用戶空間和內核空間可以有各自的2^39=512GB的虛擬地址。

需要注意到,32位應用仍然擁有512GB的內核虛擬地址空間,并且不與內核共享自己的4GB空間,但在ARM32上,32位應用只有3GB的地址空間。

ARM32和ARM64內存地址比較:


?? ?5.3 binder_become_context_manager()

binder_become_context_manager()的作用是讓servicemanager成為整個系統中唯一的上下文管理器,其實也就是service管理器,這樣我們就可以把ServiceManager稱之為守護進程。

對應的binder驅動中操作如下:

從用戶空間拷貝ioctl的參數,調用binder_ioctl_set_ctx_mgr()進行設置

BINDER_SET_CONTEXT_MGR_EXT帶參數,BINDER_SET_CONTEXT_MGR不帶參數

binder_ioctl_set_ctx_mgr()的流程也比較簡單

1、先檢查當前進程是否具有注冊Context Manager的SEAndroid安全權限

2、如果具有SELinux權限,會為整個系統的上下管理器專門生成一個binder_node節點,便該節點的強弱應用加1

3、新創建的binder_node節點,記入context->binder_context_mgr_node,即ServiceManager進程的context binder節點,使之成為serviceManager的binder管理實體


?? ?5.4 binder_loop()

? ? ? ? 下一步進行守護進程的循環處理,binder_loop()會先向binder驅動發出了BC_ENTER_LOOPER命令,告訴binder驅動“本線程要進入循環狀態了”,接著進入一個for循環不斷調用ioctl()讀取發來的數據,接著解析這些數據

其中最重要的一個結構體是binder_write_read,它用來記錄Binder buffer中讀和寫的數據信息結構體如下:

? ? 5.5 binder_parse()

? ? ? ? 在binder_loop()進入for循環之后,核心處理流程就是ioctl和binder_parse(),即不停的從Binder驅動接收讀寫數據,進行binder解析后,進行處理。

在binder_loop()中聲明了一個128字節的棧內存-readbuf,用BINDER_WRITE_READ命令從驅動讀取一些內容,并傳入binder_parse(),binder_parse()根據binder驅動傳來的“BR_XXX”協議碼,進行相關的邏輯處理,最重要的有三個“BR_XXX”協議:

BR_TRANSACTION:事務處理,解析binder_transaction_data的數據,調用回調函數svcmgr_handler()進行服務的注冊,獲取等操作

BR_REPLY:消息回復

BR_DEAD_BINDER:死亡通知

只要binder_parse()解析正常,binder_loop()就會一直執行下去,ServiceManager進程不退出。

binder_parse()解析binder驅動傳來的readbuf的內存,readbuf擁有128字節的棧內存,每次可以只處理一個cmd,也可以有多個cmd,所以存在一個while循環,可以同時解析多個cmd,多個cmd的結構體如下圖所示:

? ? ? ? 5.5.1 BR_XXX 協議碼分析

? ? ? ? BR_XXX碼,也稱為Binder響應碼,這里介紹了ServiceManager處理的一些響應碼的作用:

? ? ? ? 5.5.2 BR_TRANSACTION解析

? ? ? ? 我們這里單獨分析下BR_TRANSACTION的流程,這也是我們常用的一個流程,這是Binder驅動向Server端發送請求數據。

從readbuf中解析出binder_transaction_data的數據,最后對接收和發送數據進行了封裝,傳遞給svcmgr_handler()做詳細處理

從上main的邏輯看,我們重點關注的是binder_transaction_data這個結構,binder_transaction_data說明了transaction到底在傳輸什么語義,而語義碼就記錄在其code成員中,不同語義碼需要攜帶的數據也是不同的,這些數據由data指定。

結構體說明如下:

從上面binder_transaction_data的結構可以看出,data可存入的數據很少,主要采用了數據其實地址和數據偏移量,根據代碼上下文可知,調用了bio_init_from_txn(),從txn.transaction_data解析出binder_io的信息,存入msg

? ? ? ? 5.5.2.1 bio_init_from_txn()

bio_init_from_txn()的作用就是把binder_transaction_data的“數據起始地址”,“偏移量”,“data數據的總大小”和“偏移數組中可用的條目”:

binder_transaction_data和binder_io的關聯

初始化完binder_io的replay,并把transaction_data轉換成了binder_io的msg后,調用回調函數svcmgr_handler()進行最終邏輯處理

? ? 5.6 svcmgr_handler()

? ? ? ? 在BR_TRANSACTION的命令解析后,就把binder_transaction_data_secctx的數據傳給回調函數svcmgr_handler()進行處理。

根據不同的傳輸語義碼(txn->code)來進行相應的操作:查詢服務,注冊服務,以及列舉所服務

源碼如下:

? ? 5.7 ServiceManager是如何管理service信息的?

? ? ? ? //TODO

? ? 5.8 注冊服務

? ? ? ? 根據傳入的code:SVC_MGR_ADD_SERVICE得知,本次binder流程想要進行服務注冊。

步驟:

從binder_io msg中獲取服務名稱和長度

從binder_io msg中獲取handle

檢查該服務是否有注冊的selinx權限

查詢服務列表svclist是否存在該handle,如果有handle,就更新該服務的handle信息,通過這個handle我們最終就能找到遠端的service實體

如果svclist不存在該服務,申請一個svcinfo的空間,把服務名,長度,handle等信息存入其中

把svcinfo進入svclist的鏈表中

再以BC_ACQUIRE命令,handle為目標的信息,通過ioctl發送給binder驅動

最后以BC_REQEST_DEATH_NOTIFICATION命令的信息,通過ioctl發送給binder驅動,主要用于清理內存等收尾工作? ? ? ??

? ? 5.9 查找服務

? ? ? ? //TODO

6、總結

? ? ? ? //TODO

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/162013.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/162013.shtml
英文地址,請注明出處:http://en.pswp.cn/news/162013.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

廣告機/商業顯示屏_基于MT878安卓主板方案

安卓主板在廣告機領域扮演著重要的角色。無論是在商場、車站、酒店、電梯、機場還是高鐵站,LED廣告機廣泛應用,并通過不同方式進行播放和管理。 廣告機/商業顯示屏_基于MT878安卓主板方案 基于MT8788安卓主板方案的廣告機采用了聯發科MT8788八核芯片方案…

對比兩個數組中對應位置的兩個元素將每次對比的最大值用于構成新的數組np.maximum()

【小白從小學Python、C、Java】 【計算機等考500強證書考研】 【Python-數據分析】 對比兩個數組中對應位置的兩個元素 將每次對比的最大值用于構成新的數組 np.maximum() 選擇題 以下代碼的輸出結果為? import numpy as np a1 [1,2,33] a2 [11,2,3] print("…

Axios 默認配置 簡化URL 簡化代碼 多臺服務器接口配置

main.js配置 import Axios from axios Axios.defaults.method GET//設置默認的請求類型 Axios.defaults.baseURL https://apis.jxcxin.cn/api//設置接口地址 Axios.defaults.params { token: abc } //每次請求都帶上這個參數 Axios.defaults.timeout 5000 //請求的超時時間…

MATLAB - text的兩種使用方法

text小技巧 1. 常規使用(Method 1)2. 在顯示畫面的相對位置(Method 2)3. 舉個例子 1. 常規使用(Method 1) text(x,y,txt)2. 在顯示畫面的相對位置(Method 2) text(string,‘ABC’,…

使用websocket獲取thingsboard設備的實時數據

背景 有一個讀者前來咨詢,如何實時獲取設備的遙測數據。 其實tb是有提供websocket接口來獲取設備數據的。而且還支持js跨域調用。下面給大家演示一下。 websocket地址 完整代碼 <!DOCTYPE HTML> <html><h

HTTP協議和WebSocket協議之間的區別

HTTP協議和WebSocket協議之間的主要區別在于它們的設計目的和通信方式。 HTTP協議是一種無狀態的協議&#xff0c;它的主要設計目的是用于從Web服務器傳輸超文本到本地瀏覽器的傳輸協議。HTTP協議使用請求和響應模型&#xff0c;客戶端向服務器發送請求&#xff0c;服務器返回…

【Java并發編程十二】線程池

線程池 用來統一地管理線程&#xff0c;避免線程的重復創建與銷毀。使用線程池可以讓執行完的線程回到線程池&#xff0c;等待下一次調用。 import jdk.jshell.EvalException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import j…

Matplotlib顏色條的配置_Python數據分析與可視化

Matplotlib顏色條配置 基本顏色顏色條選擇配色方案顏色條刻度的限制與擴展功能的設置離散型顏色條 基本顏色 Matplotlib提供了8種指定顏色的方法&#xff1a; 在[0&#xff0c;1]中的浮點值的RGB或RGBA元組&#xff08;例如 (0.1, 0.2, 0.5) 或&#xff08;0.1&#xff0c; 0.…

C語言中文網 - Shell腳本 - 9

第1章 Shell基礎(開胃菜) 9. Shell修改命令提示符 Shell 通過PS1和PS2這兩個環境變量來控制提示符的格式,修改PS1和PS2的值就能修改命令提示符的格式。 PS1 控制最外層的命令提示符格式。 PS2 控制第二層的命令提示符格式。 在修改 PS1 和 PS2 之前,我們先用 echo 命令輸出…

contos7中mongodb數據庫無法備份與還原,數據庫工具的安裝

由于之前數據庫沒有卸載干凈&#xff0c;導致直接用sudo yum install -y mongodb-org-tools命令無法直接安裝&#xff0c;只能選擇手動安裝了。 先去官網找到mongo-tool工具 MongoDB Database Tools Downloads | MongoDB 然后復制要下載的版本的地址。 然后直接用wget來下載 …

【每日OJ —— 622. 設計循環隊列】

每日OJ —— 622. 設計循環隊列 1.題目&#xff1a;622. 設計循環隊列2.解法2.1.解法講解2.1.1.算法講解2.1.2.代碼實現2.1.3.提交通過展示 1.題目&#xff1a;622. 設計循環隊列 2.解法 1.本題有很多解法&#xff1a;可以使用數組&#xff0c;單鏈表&#xff0c;雙鏈表&#x…

2023亞太杯數學建模賽題人工精準翻譯

大家好&#xff0c;亞太杯今天早上6點已經開賽啦&#xff0c;然后我在這里給大家帶來賽題的精準人工翻譯&#xff0c;防止大家直接用軟件翻譯導致某些地方亂碼或者翻譯不精準&#xff0c;這會導致后續做題過程出現很大偏差。 注意&#xff0c;以下翻譯均免費發放word形式的哈&…

【精選】CSS入門必看知識點大合集

CSS簡介 CSS概念 CSS&#xff08;Cascading Style Sheets&#xff09;層疊樣式表&#xff0c;又叫級聯樣式表&#xff0c;簡稱樣式表 CSS文件后綴名為.css CSS用于HTML文檔中元素樣式的定義 為什么需要CSS 使用css的唯一目的就是讓網頁具有美觀一致的頁面 語法 CSS 規則…

DB2—03(DB2中常見基礎操作)

DB2—03&#xff08;DB2中常見基礎操作&#xff09; 1. 前言1.1 oracle和mysql相關 2. db2中的"dual"2.1 SYSIBM.SYSDUMMY12.2 使用VALUES2.3 SYSIBM.SYSDUMMY1 "變" dual 3. db2中常用函數3.1 nvl()、value()、COALESCE()3.2 NULLIF() 函數3.3 LISTAGG() …

論文《Unsupervised Dialog Structure Learning》筆記:詳解DD-VRNN

D-VRNN模型和DD-VRNN模型 總體架構 離散-可變循環變分自編碼器&#xff08;D-VRNN&#xff09;和直接-離散-可變循環變分自編碼器&#xff08;DD-VRNN&#xff09;概述。D-VRNN和DD-VRNN使用不同的先驗分布來建模 z t z_t zt?之間的轉換&#xff0c;如紅色實線所示。 x t x_t…

Rust錯誤處理:Result

文章目錄 簡介錯誤匹配 Rust基礎教程&#xff1a; 初步? 所有權? 結構體和枚舉類? 函數進階? 泛型和特征? 并發和線程通信? cargo包管理? 可空類型Option Rust進階教程&#xff1a; 用宏實現參數可變的函數? 類函數宏 簡介 Rust中沒有提供類似try…catch之類…

qt雙擊treeview節點之后,完成編輯,獲取完成編輯得信號

Qt 中&#xff0c;要獲取 QTreeView 節點完成編輯的信號&#xff0c;您可以使用 QTreeView 的 doubleClicked 信號以及重寫相應的編輯觸發函數。通常情況下&#xff0c;完成編輯后會觸發 closeEditor 信號。 以下是一個示例代碼&#xff0c;演示了如何實現這個功能&#xff1a…

【亞太杯思路助攻】2023年第十三屆APMCM亞太地區大學生數學建模競賽——(文末領取方式)

2023年第十三屆APMCM亞太地區大學生數學建模競賽——正式開賽&#xff01;&#xff01;&#xff01; 賽題已由高分雅思學姐翻譯完成&#xff0c;我們的O獎學長也在第一時間分析了賽題&#xff0c;幫助大家最快時間&#xff0c;選擇最適合是自己的賽題。 B題 C題 祝各位小伙伴都…

[Android]使用Retrofit進行網絡請求

以下是使用 Retrofit 發送 POST 請求獲取分頁城市列表的 Kotlin 代碼示例 1.在你的 build.gradle 文件中添加 Retrofit 和 Gson 的依賴 dependencies {......implementation("com.squareup.retrofit2:retrofit:2.9.0")implementation("com.squareup.retrofit2…