Understanding Binder in Android Haifeng Li 2014-9-2
Jul 07, 2015
Outline
• Background
– What is Binder
– Binder Communication Model
– Terminology
– Binder Software Stack
• Client(user space)
• Binder driver (Kernel Space)
• Service(user space)
Background
• What is Binder?
– An Inter-process communication system for developing object-oriented OS services.
client server
Data
Binder Communication Model
User Space
Kernel Space
Cclientservice
Binder Driver
ioctl/open/... ioctl/open/...
mIn mOut
ioctl/open/...
mIn mOut mIn mOut
Service Manager/system/bin/servicemanager
C
Get Service Add Service
Service 1 – handle 1
Service 2 – handle 2...
Terminology
• Service Handle
• Remote Binder
• Local Binder
• Binder node
• Binder reference
• Service Manager(Context Manager)
– It’s handle is 0 in all binder client and server.
Binder Driver
Remote Binder/Handle Local Binder
Binder NodeBinder ref.
IPC Software Stack
App1 service
Proxy(BpBinder) Stub(BnBinder)
IPCThreadState IPCThreadState
Binder Module
User Space
Kernel Space
Client Server
1
2
3 4
5
6
1. BpBinder(n) -> transact(OP, data, &reply) 2. IPCThreadState::transact(handle, OP, data, reply) 3. ioctl(binder_fd, BINDER_OPERATION, &bwr) 4. IPCThreadState::getAndExecuteCommand() 5. Bnxxx::onTransact(OP, data, reply)
Client(user space)
• Initialization
– Call system call open(), which is binder_open in kernel. Open /dev/binder file and get a file description. Create some key data structures.
– mmap 1MB-8KB virtual space for data transaction by binder_mmap in kernel.
• Get handle of service from service manager
• Sent request to Service by BpBinder(handle)
• Data transact to kernel by IPCThreadState.
App1 service
Proxy(BpBinder) Stub(BnBinder)
IPCThreadState IPCThreadState
Binder Module
User Space
Kernel Space
Client Server
1
2
3 4
5
6
Data Transaction in Client(1)
• Package in Client 102 virtual void Client::Foo(int32_t push_data) { 103 Parcel data, reply; 104 data.writeInterfaceToken(IDemo::getInterfaceDescriptor()); 105 data.writeInt32(push_data);//writeStrongBinder(service) 109 110 remote()->transact(OP, data, &reply);
Parcel...flat_binder_objectmData flat_binder_object
mObjects
Service
Data Transaction in Client(2)
• Packaged to binder_transaction_data IPCThreadState::writeTransactionData(int32_t cmd, …, int32_t handle, uint32_t code, const Parcel& data…) •cmd will add to mData.(BC_TRANSACTION, BC_REPLY,… Binder Command) •Target: target handle •Cookie: will be define according to handle in binder driver •Code: Operation of client. •Offsets could help the binder driver to process binder object reference.
Parcel...flat_binder_objectmData flat_binder_object
mObjects
target
cookie
code
...
data.ptr.buffer
data.ptr.offsets
...
binder_transaction_data
Data Transaction in Client(3)
• Binder Command(User->Driver) – Binder Thread Support: BC_REGISTER_LOOPER, BC_ENTER LOOPER,BC_EXIT_LOOPER
– Binder Transactions: BC_TRANSACTION, BC_REPLY
– Further Mechanism: BC_INCREFS, BC_RELEASE , BC_DECREFS, BC_REQUEST_DEATH_NOTIFICIATION, BC_CLEAR_DEATH_NOTIFICATION, BC_DEAD_BINDER_DONE,…
• Binder Return Command (Driver -> User) – Binder Thread Support: BR_SPAWN_LOOPER
– Binder Transactions: BR_TRANSACTION, BR_REPLY
– Further Mechanism: BR_INCREFS,BR_ACQUIRE, BR_RELEASE , BR_DECREFS, BR_CLEAR_DEATH_NOTIFICATION_DONE, …
Client ServerDriver
BC_TRANSACTION
BR_TRANSACTION
BC_REPLYBR_REPLY
BC_FREE_BUFFER
BC_FREE_BUFFER
Data Transaction in Client(4)
• Repackage to Parcel(mOut)
• Each working thread has two parcel: mOut and mIn. mOut is for write buffer, mIn for read buffer.
Parcel
cmd binder_transactin_datamDatawrite_size
Write_buffer
Read_size
Read_buffer
binder_write_read
Outline
• Background
• Client(user space)
• Binder driver (Kernel Space)
• Service(user space)
App1 service
Proxy(BpBinder) Stub(BnBinder)
IPCThreadState IPCThreadState
Binder Module
User Space
Kernel Space
Client Server
1
2
3 4
5
6
Binder Driver:Binder Protocol
• The protocol used for ioctl() system call.
– BINDER_WRITE_READ
– BINDER_SET_MAX_THREADS
– BINDER_SET_CONTEXT_MGR
– BINDER_THREAD_EXIT
– BINDER_VERSION
– BINDER_SET_IDLE_TIMEOUT
Key Data Structure (1)
Binder Driver
Process 1 Process 2 Process 3
binder_proc binder_proc binder_proc
threads node refs_by_desc refs_by_node
• The binder_proc is mapped to process by 1:1. It is created on binder_open(). • All binder_proc are listed in binder_procs. • The binder_proc has 4 red-black tree. • The binder_thread represents a working thread, inserted into threads rbtree. • The binder_node represents a service, inserted into node rbtree. • refs_by_desc and refs_by_node represent reference to a proc_node.
Key Data Structure (2)
User spaceKernel space
BpBinder
Remote Binder
BBinder
Local Binder
binder_proc
node
refs_by_node
binder_proc
node
refs_by_node
binder_ref
binder_node
Key Data Structure (3)
...
todo
thread
binder_proc
binder_thread
todo
binder_work binder_work
binder_work binder_work
...
...
binder_transaction
binder_transaction
Input Data Format
Parcel
Parcel
write_sizewrite_buffer
read_sizeread_buffer
binder_write_read
bufferdata_sizeoffsets
...
binder_transaction_data
code
cookiehandle
offset 1offset 2
...
...
flat_binder_object
flat_binder_object
BC_TRANSACTION
BC_XXX
Xxxx data struct
mOut
...
head
IPCThreadState Client
Transaction in Binder – Client (1)
1. Copy binder_write_read from user space
2. Copy xxx data to kernel space. Iterate the items: ① Get Binder command from write_buffer(BC_XXX).
② Get target thread/proc/node by handle.
③ Allocate binder_buffer from target space, and copy effective data.
④ Build a session(build_transaction).
⑤ Mount the session to target_thread’s todo list.
⑥ Mount a BINDER_WORK_TRANSACTION_COMPLETE binder_work to source thread
⑦ Wake up corresponding thread.
Parcel
Parcel
write_sizewrite_buffer
read_sizeread_buffer
binder_write_read
bufferdata_sizeoffsets...
binder_transaction_data
code
cookiehandle
offset 1offset 2
...
...
flat_binder_object
flat_binder_object
BC_TRANSACTION
BC_XXX
Xxxx data struct
mOut
...
head
IPCThreadState Client
1
2
①
②
③
Transaction in Binder –Client (2)
Target Space
data
Copy
Parcel
Parcel
write_sizewrite_buffer
read_sizeread_buffer
binder_write_read
bufferdata_sizeoffsets
...
binder_transaction_data
code
cookiehandle
offset 1offset 2
...
...
flat_binder_object
flat_binder_object
BC_TRANSACTION
BC_XXX
Xxxx data struct
mOut
...
head
IPCThreadStateClient
bufferpriorityoffsets
sender_euid
binder_transaction
code
to_threadto_proc
data
...
offsets_sizedata_sizetarget_node
binder_buffer
Offsets[]
Copy
Transaction in Binder -- Server
1. Server thread wake up and get a binder_work(binder_transaction) from todo list
2. Build a binder_transaction_data from binder_transaction
3. Set priority of current thread of client.
4. The buffer and offsets will be virtual address – Virtual address = kernel address + address offset
5. Copy binder_transaction_data to mIn
6. Return from kernel
7. IPCThreadState iternate the command and data. – For BR_TRANSACTION, call stub’s onTransact function,
which will call server service function finally.
Target Space
databufferpriorityoffsets
sender_euid
binder_transaction
code
to_threadto_proc
data
...
offsets_sizedata_sizetarget_node
binder_buffer
Offsets[]
bufferdata_sizeoffsets...
binder_transaction_data
code
cookiehandle
Kernel Space
write_sizewrite_buffer
read_sizeread_buffer
binder_write_read
Parcel
mIn
BR_NOOP
Data
binder_transaction_data
BR_TRANSACTION
Copy to user
User Space
Transaction stack(1)
• The stack is for recording transaction session.
• Commonly, to_parent and from_parent is null. But, when the transaction rely on other session, what will happen? – The session in B will lost.
A
(list_head)todo
Binder_thread
B
Binder_thread
transaction_stack
wait queue
...
(list_head)todo
transaction_stack
wait queue
...
to_parentfrom_parent
...sender_euid
binder_transaction
...
to_threadtodo