Binder驅動的代碼都在kernel里面,這里就簡單講一下里面涉及到的幾個東西:
1.Memory
Binder其實本質上就是一中數據傳輸方式,這種方式是通過binder driver實現的。
我們知道其他的一些IPC的方法,在傳遞數據的時候,一般都會有兩次拷貝,發送者拷貝到底層,底層再拷貝給接收者。
但是Binder通過共享內存進行通信,只有一次copy。
看下面的圖中,每個涉及到Binder通信的進程,都會有一個共享內存,它是binder驅動和進程之間的共享內存。但是進程是無法對內存進行寫操作的,是只讀的。
Process A向Process B傳遞數據時,這些數據會被driver從ProcessA copy 到 binder和ProcessB之間的共享內存中。ProcessB已經映射過地址,就可以直接讀取內存里面的數據了,就不需要再做一次拷貝動作了
在ProcessState初始化的時候,就會調用mmap()去映射地址。
./frameworks/native/libs/binder/ProcessState.cpp
1 ProcessState::ProcessState() 2 : mDriverFD(open_driver()) 3 , …. 4 { 5 if (mDriverFD >= 0) { 6 mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); 7 ... 8 } 9 }
2.binder_ref / binder_node
我們拿到一個代理對象,通過binder驅動來調用遠程的服務,那Binder到底是如何根據代理對象找到實體對象的呢?
其實Binder驅動會在內核為process創建一個binder_proc 結構提,在binder_proc中保存着四個RB Tree。
其中三個tree就是保存binder_ref和binder_node的。就是傳遞來傳遞去的代理對象和實體對象。
一個tree保存binder_node;另外兩個tree保存binder_ref,這兩個tree的內容其實都一樣,只是為了便於搜索,就建了兩個不同key的tree。
這三個tree都具體存寫什么東西?
-->這樣說,一個process里有個實體對象,就有多少個binder_node;一個process有多少個代理對象指向遠端,就有多少個binder_ref.
看下面的圖中:
ProcessA向binder驅動傳入一個handle,binder驅動就會根據handle在tree中找到對應的binder_ref。 binder_ref里面有一個node變量, 它就是對應的實體對象的node的地址,靠它找到對應的binder_node。然后在binder_node里面,也有一個變量:cookie,它就是BBinder的地址。找到BBinder就OK了。