博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android Binder(zt)
阅读量:4074 次
发布时间:2019-05-25

本文共 2590 字,大约阅读时间需要 8 分钟。

這個系列是讀書筆記,作者可能沒有跟主題有關的開發經驗。

Binder 是 android 大量使用的 IPC 機制。當使用者在 launcher (home) 按了某個 App 時,這個動作會經由 ActivityManager 向 zygote 發出請求,並從 zygote fork 出新的 process 執行被選擇的 App。這個過程大致上有 4 個 process 參與:home、system server、zygote 和新產生的 appA。更仔細去看的話,
  1. system server 向 home 送出 touchscreen 事件
  2. home 向 system server 送出 start activity 事件
  3. system server 向 zygote 送出 appA 的啟動參數
  4. appA 向 system server 送出 attach 事件


除 了第 3 項以外,其它跨 process 的溝通都是採用 binder。Zygote 是 android 上少數幾個聽 unix socket 的程式。驗證這個說法最簡單的方法是去看 process 的 memory maps 還有 opened fd,這個技巧在
有用過,這邊暫且略過。


一 個 IPC 機制的效能很大一部份取決於它資料交換的能力,從這點去切入是不錯的途徑。所有參與 binder 的 process 都會在一開始向 /dev/binder 裝置 mmap 一塊 read-only 的記憶體,大小在幾個 MB 左右。A process 傳送資料給 B process 的做法是,由 A 對 /dev/binder 做 ioctl 將資料先送給 binder driver。依資料大小,binder driver 動態配置足夠的 physical memory 存放來自 A 的資料,並在 B 一開始 mmap 得到的 address space 裡尋找一段足夠大且未使用的 address area。找到後,binder driver 會修改 B 的 page table,讓這段 address area 映射到剛剛動態配置的 physical memory。如此一來,B 可以直接存取 A 送過來的資料;等到 B 不需要這些資料時,再由 B 負責把這塊記憶體還回去給系統。這段實作可以參改 binder driver 的 binder_update_page_range 函數。


Process 對 binder 的操作只透過 ioctl 做 buffer 的讀寫。Buffer 的內容是一系列的 (command, argument) 組。每個 command 為 4 bytes,argument 的長度視 command 而定,可能是固定的,也可能是變動的。當 A 跟 B 交換資料時,通常會由一方送出 BC_TRANSACTION command,再由另一方回覆 BC_REPLY command。Transaction/reply 的 argument 除了一段 header 外,其餘的資料部份會使用上一段討論的方式做交換。資料的長度跟內容由 A、B 另行約定,可能是整數、浮點數或字串等。除了上述的基本資料型別外,還有三種用 struct flat_binder_object 表示的特殊型別:BINDER、HANDLE、FD。FD 型別讓 A、B 可以交換 file descriptor,也就是說,A 可以打開某個檔案,把 fd 傳給 B,讓 B 去讀寫。或者說,也是更重要的,surface manager 可以準備一塊 surface,把 surface 的 fd (一塊 ashmem 記憶體) 傳給一個 app,讓 app 可以在上面作畫。有了這層理解,我們對 android 可以有更自由的發揮,例如,可以不改一行 cairo 的程式碼,就利用 cairo 與 c++ 寫出一個會動的時鐘:


xxxx


回 到正題,我們知道 binder 還有 BINDER 與 HANDLE 這兩個特殊型別。它們的功用可以用 service port 跟 connection 做類比。就像 httpd 可以開 80 port 提供服務,client 可以跟它建立 connection 使用服務一樣,在 android 上頭,WindowManagerService 可能建立了一個 BINDER,提供了視窗操作的服務。其它程式可能會建立這個服務的 HANDLE。在 binder 之上,android 提供了 aidl 讓開發者可以把 remote service 當做 local object 操作,所以開發者可以直接呼叫 mWindowManager.setRotation 來旋轉螢幕,而幾乎可以不用知道 BINDER 跟 HANDLE 的存在。


當 一個 process 收到 transaction 的時候,如果 binder driver 發現 process 沒有任何 thread 已經準備好等著要處理,等到下次有 thread 來處理時,它會收到 BR_SPAWN_LOOPER 的訊息,userspace 也會多產生一個 thread 專門對 /dev/binder 做 I/O,確保下次有 transaction 的時候,有比較高的機會是已經有 thread 準備好了。提個數字,在 android sdk 1.5 preview 的 emulator 剛開好機時,在我的機器上,Phone App 會有 11 個 thread,而其中有 6 個 thread 是跑在同一個迴圈裡等著對 /dev/binder 做 I/O。這項機制相信是為了縮短應用程式的反應時間。


Binder 再探討下去還有許多東西可以討論,例如 android native library 沒有 aidl 可以用,它如何建立操作 binder 的物件?或者 native code 裡面常常看到的 sp<>、wp<> 跟 binder 的 reference counting 關係為何?對 binder 的功能有初步認識後,再去理解這些實作會顯得直覺許多。

转载地址:http://ctuni.baihongyu.com/

你可能感兴趣的文章
Introducing Holographic Emulation
查看>>
新手!mass 设置问题
查看>>
AS3语法和UNITY C#语法的异同
查看>>
ACCELEROMETER
查看>>
在后台中高效工作 – 后台任务
查看>>
half extents
查看>>
Unity需要频繁登录是什么情况
查看>>
UNITY自带的PACKAGE的UTILITY 里面有一个自带的FPS COUNTER
查看>>
AssetBundle Manager & Example Scenes
查看>>
fixed数据类型
查看>>
cg数据类型
查看>>
地图四叉树一般用在GIS中,在游戏寻路中2D游戏中一般用2维数组就够了
查看>>
Dijkstra算法(三)之 Java详解
查看>>
float4与half4数据类型
查看>>
安装Windows更新程序遇到错误:0x80070422
查看>>
Fresnel Reflection - 菲涅尔反射
查看>>
BRDF 光照模型
查看>>
unity编辑器的搜索框好特么坑啊,居然不支持*号通配符
查看>>
场景中,并没有灯源的存在,但是cube却会有灯光照射的反应,这就是Light Probe Group的作用。...
查看>>
unity3d 为什么要烘焙?烘焙作用是为了什么?
查看>>