導航:首頁 > 操作系統 > androidnative方法

androidnative方法

發布時間:2023-08-18 01:07:52

android通信方式篇(七)-Binder機制(Native層(下))

本篇文章針對向ServiceManager注冊服務 和 獲取服務兩個流程來做總結。在這兩個過程中,ServiceManager都扮演的是服務端,與客戶端之間的通信也是通過Binder IPC。

在此之前先了解下Binder的進程與線程的關系:

用戶空間 :ProcessState描述一個進程,IPCThreadState對應一個進程中的一個線程。
內核空間 :binder_proc描述一個進程,統一由binder_procs全局鏈表保存,binder_thread對應進程的一個線程。
ProcessState與binder_proc是一一對應的。

Binder線程池 :每個Server進程在啟動時會創建一個binder線程池,並向其中注冊一個Binder線程;之後Server進程也可以向binder線程池注冊新的線程,或者Binder驅動在探測到沒有空閑binder線程時會主動向Server進程注冊新的的binder線程。對於一個Server進程有一個最大Binder線程數限制15,(#define DEFAULT_MAX_BINDER_THREADS 15)。對於所有Client端進程的binder請求都是交由Server端進程的binder線程來處理的。我的理解是:binder線程是進程進行binder ipc時的一條數據處理路徑。

MediaPlayerService向ServiceManager注冊過程如下:

相關類:

整個過程總結如下:
1 獲取BpServiceManager 與 BpBinder
由defaultServiceManager()返回的是BpServiceManager,同時會創建ProcessState對象和BpBinder對象。然後通過BpBinder執行transact,把真正工作交給IPCThreadState來處理。

2 BpBinder transact
Binder代理類調用transact()方法,真正工作還是交給IPCThreadState來進行transact工作。

3 通過IPCThreadState 包裝並轉換數據並進行transact事務處理
每個線程都有一個IPCThreadState,每個IPCThreadState中都有一對Parcel變數:mIn、mOut。相當於兩根數據管道:

最後執行talkWithDriver。

writeTransactionData:將BC Protocol + binder_transaction_data結構體 寫入mOut, 然後執行waitForResponse:

由talkWithDriver將數據進一步封裝到binder_write_read結構體,通過ioctl(BINDER_WRITE_READ)與驅動通信。同時等待驅動返回的接收BR命令,從mIn取出返回的數據。

mIn包裝的數據結構(注冊服務handle = 0 ,code 為ADD_SERVICE_TRANSACTION):

4 Binder Driver
把binder_write_read結構體write_buffer里數據取出來,分別得到BC命令和封裝好數據的事務binder_transaction_data, 然後根據handler,在當前binder_proc中,找到相應的binder_ref,由binder_ref再找到目標binder_node實體,由目標binder_node再找到目標進程binder_proc。然後就是插入數據:當binder驅動可以找到合適的線程,就會把binder_transaction節點插入到servciemanager的線程的todo隊列中,如果找不到合適的線程,就把節點之間插入servciemanager的binder_proc的todo隊列。

5 ServiceManager
經過Binder Driver的處理,數據已經到了ServiceManager進程,在BR_TRANSACTION的引導下,在binder_loop()中執行binder_parser()取出數據,執行do_add_service()操作,最終向 svcinfo 列表中添加已經注冊的服務(沒有數據的返回)。最後發送 BR_REPLY 命令喚醒等待的線程,通知注冊成功。結束MediaPlayerService進程 waitForResponse()的狀態,整個注冊過程結束。

獲取服務的過程與注冊類似,首先 ServiceManager 向 Binder 驅動發送 BC_TRANSACTION 命令攜帶 CHECK_SERVICE_TRANSACTION 命令,同時獲取服務的線程進入等待狀態 waitForResponse()。Binder 驅動收到請求命令向 ServiceManager 的發送 BC_TRANSACTION 查詢已注冊的服務,會區分請求服務所屬進程情況。

查詢到直接響應 BR_REPLY 喚醒等待的線程。若查詢不到將與 binder_procs 鏈表中的服務進行一次通訊再響應。

以startService為例來簡單總結下執行流程:

3.1 從方法執行流程來看:

Client :

1 AMP.startService 標記方法以及通過Parcel包裝數據;

2 BinderProxy.transact 實際調用native的 android_os_BinderProxy_transact 傳遞數據;

3 獲取BpServiceManager 與 BpBinder 同時會創建ProcessState。然後通過BpBinder執行transact,把真正工作交給IPCThreadState來處理;

4 IPC.transact 主要執行writeTransactionData,將上層傳來的數據重新包裝成binder_transaction_data,並將BC Protocol + binder_transaction_data結構體 寫入mOut;

5 IPC waitForResponse talkWithDriver + 等待返回數據;

6 talkWithDriver 將數據進一步封裝成binder_write_read,通過ioctl(BINDER_WRITE_READ)與驅動通信;

Kernel :

7 binder ioctl 接收BINDER_WRITE_READ ioctl命令;

8 binder_ioctl_write_read 把用戶空間數據ubuf拷貝到內核空間bwr;

9 binder_thread_write 當bwr寫緩存有數據,則執行binder_thread_write;當寫失敗則將bwr數據寫回用戶空間並退出;

10 binder_transaction 找到目標進程binder_proc並插入數據到目標進程的線程todo隊列,最終執行到它
時,將發起端數據拷貝到接收端進程的buffer結構體;

11 binder_thread_read 根據binder_transaction結構體和binder_buffer結構體數據生成新的binder_transaction_data結構體,寫入bwr的read_buffer,當bwr讀緩存有數據,則執行binder_thread_read;當讀失敗則再將bwr數據寫回用戶空間並退出;最後,把內核數據bwr拷貝到用戶空間ubuf。

12 binder_thread_write + binder_ioctl BR命令和數據傳遞

Server:

13 IPC.executeCommand 解析kernel傳過來的binder_transaction_data數據,找到目標BBinder並調用其transact()方法;

14 IPC.joinThreadPool 採用循環不斷地執行getAndExecuteCommand()方法, 處理事務。當bwr的讀寫buffer都沒有數據時,則阻塞在binder_thread_read的wait_event過程. 另外,正常情況下binder線程一旦創建則不會退出.

15 BBinder.transact 到Binder.exeTransact 調用 AMN.onTransact

16 AMN.onTransact 把數據傳遞到AMS.starService去執行

17 AMS.starService Server處理了Client的請求了

然後原路replay回去,talkWithDriver 到Kernel ,然後找到Client進程,把數據拷貝到read_buffer里,最終喚醒IPC,把反饋傳遞回AMP.startService。完成啟動服務。

3.2 從通信協議流程來看:

非oneWay:

oneway:

oneway與非oneway區別: 都是需要等待Binder Driver的回應消息BR_TRANSACTION_COMPLETE. 主要區別在於oneway的通信收到BR_TRANSACTION_COMPLETE則返回,而不會再等待BR_REPLY消息的到來. 另外,oneway的binder IPC則接收端無法獲取對方的pid.

3.3 從數據流來看

從用戶空間開始:

進入驅動後:

回到用戶空間:

參考:
http://gityuan.com/2016/09/04/binder-start-service/
http://gityuan.com/2015/11/28/binder-summary/
http://gityuan.com/2015/11/14/binder-add-service/
http://gityuan.com/2015/11/15/binder-get-service/

閱讀全文

與androidnative方法相關的資料

熱點內容
裘錫圭pdf 瀏覽:720
android模擬器調試 瀏覽:129
sap命令大全 瀏覽:290
mysql導出數據命令 瀏覽:949
文件夾隱藏了出不來 瀏覽:562
電信網上大學源碼 瀏覽:204
rr輪轉調度演算法 瀏覽:253
我的世界無法登入伺服器怎麼辦 瀏覽:148
文件加密授權特定隱藏訪問控制 瀏覽:801
程序員劍靈官網 瀏覽:516
php調用static方法 瀏覽:934
天正命令版 瀏覽:86
聚合支付加密幣 瀏覽:313
蜜源app是什麼時候創立的 瀏覽:706
計算機專業學51單片機 瀏覽:210
程序員不接受反駁 瀏覽:298
微軟自帶的壓縮軟體 瀏覽:289
中國玩家在日本伺服器做什麼 瀏覽:51
12864和單片機 瀏覽:898
25匹空調壓縮機 瀏覽:649