Binder通信简述
Client进程通过RPC(Remote Procedure Call Protocol)与Server通信,可以简单地划分为三层,驱动层、IPC层、业务层。demo()便是Client端和Server共同协商好的统一方法;handle、RPC数据、代码、协议这4项组成了IPC层的数据,通过IPC层进行数据传输;而真正在Client和Server两端建立通信的基础设施便是Binder Driver。
Binder通信协议
先列举一次完整的Binder通信过程:
Binder协议包含在IPC数据中,分为两类:
- BINDER_COMMAND_PROTOCOL:binder请求码,以”BC_“开头,简称BC码,用于从IPC层传递到Binder Driver层;
- BINDER_RETURN_PROTOCOL :binder响应码,以”BR_“开头,简称BR码,用于从Binder Driver层传递到IPC层;
Binder IPC通信至少是两个进程的交互:
- client进程执行binder_thread_write,根据BC_XXX命令,生成相应的binder_work;
- server进程执行binder_thread_read,根据binder_work.type类型,生成BR_XXX,发送到用户空间处理。
通信过程
binder_thread_write
请求处理过程是通过binder_thread_write()方法,该方法用于处理Binder协议中的请求码。当binder_buffer存在数据,binder线程的写操作循环执行。
1 | binder_thread_write(){ |
对于请求码为BC_TRANSACTION或BC_REPLY时,会执行binder_transaction()方法,这是最为频繁的操作。 对于其他命令则不同。
binder_transaction
1 | static void binder_transaction(struct binder_proc *proc, |
BC_PROTOCOL
binder请求码,是用enum binder_driver_command_protocol来定义的,是用于应用程序向binder驱动设备发送请求消息,应用程序包含Client端和Server端,以BC_开头,总17条;(-代表目前不支持的请求码)
请求码 | 参数类型 | 作用 |
---|---|---|
BC_TRANSACTION | binder_transaction_data | Client向Binder驱动发送请求数据 |
BC_REPLY | binder_transaction_data | Server向Binder驱动发送请求数据 |
BC_FREE_BUFFER | binder_uintptr_t(指针) | 释放内存 |
BC_INCREFS | __u32(descriptor) | binder_ref弱引用加1操作 |
BC_DECREFS | __u32(descriptor) | binder_ref弱引用减1操作 |
BC_ACQUIRE | __u32(descriptor) | binder_ref强引用加1操作 |
BC_RELEASE | __u32(descriptor) | binder_ref强引用减1操作 |
BC_ACQUIRE_DONE | binder_ptr_cookie | binder_node强引用减1操作 |
BC_INCREFS_DONE | binder_ptr_cookie | binder_node弱引用减1操作 |
BC_REGISTER_LOOPER | 无参数 | 创建新的looper线程 |
BC_ENTER_LOOPER | 无参数 | 应用线程进入looper |
BC_EXIT_LOOPER | 无参数 | 应用线程退出looper |
BC_REQUEST_DEATH_NOTIFICATION | binder_handle_cookie | 注册死亡通知 |
BC_CLEAR_DEATH_NOTIFICATION | binder_handle_cookie | 取消注册的死亡通知 |
BC_DEAD_BINDER_DONE | binder_uintptr_t(指针) | 已完成binder的死亡通知 |
BC_ACQUIRE_RESULT | - | - |
BC_ATTEMPT_ACQUIRE | - | - |
binder_thread_read
响应处理过程是通过binder_thread_read()方法,该方法根据不同的binder_work->type以及不同状态,生成相应的响应码。
1 | binder_thread_read(){ |
当transaction堆栈为空,且线程todo链表为空,且non_block=false时,意味着没有任何事务需要处理的,会进入等待客户端请求的状态。当有事务需要处理时便会进入循环处理过程,并生成相应的响应码。在Binder驱动层,只有在进入binder_thread_read()方法时,同时满足以下条件, 才会生成BR_SPAWN_LOOPER命令,当用户态进程收到该命令则会创建新线程:
- binder_proc的requested_threads线程数为0;
- binder_proc的ready_threads线程数为0;
- binder_proc的requested_threads_started个数小于15(即最大线程个数);
- binder_thread的looper状态为BINDER_LOOPER_STATE_REGISTERED或BINDER_LOOPER_STATE_ENTERED。
BR_PROTOCOL
binder响应码,是用enum binder_driver_return_protocol来定义的,是binder设备向应用程序回复的消息,,应用程序包含Client端和Server端,以BR_开头,总18条;’
响应码 | 参数类型 | 作用 |
---|---|---|
BR_ERROR | __s32 | 操作发生错误 |
BR_OK | 无参数 | 操作完成 |
BR_NOOP | 无参数 | 不做任何事 |
BR_SPAWN_LOOPER | 无参数 | 创建新的Looper线程 |
BR_TRANSACTION | binder_transaction_data | Binder驱动向Server端发送请求数据 |
BR_REPLY | binder_transaction_data | Binder驱动向Client端发送回复数据 |
BR_TRANSACTION_COMPLETE | 无参数 | 对请求发送的成功反馈 |
BR_DEAD_REPLY | 无参数 | 回复失败,往往是线程或节点为空 |
BR_FAILED_REPLY | 无参数 | 回复失败,往往是transaction出错导致 |
BR_INCREFS | binder_ptr_cookie | binder_ref弱引用加1操作(Server端) |
BR_DECREFS | binder_ptr_cookie | binder_ref弱引用减1操作(Server端) |
BR_ACQUIRE | binder_ptr_cookie | binder_ref强引用加1操作(Server端) |
BR_RELEASE | binder_ptr_cookie | binder_ref强引用减1操作(Server端) |
BR_DEAD_BINDER | binder_uintptr_t(指针) | Binder驱动向client端发送死亡通知 |
BR_CLEAR_DEATH_NOTIFICATION_DONE | binder_uintptr_t(指针) | BC_CLEAR_DEATH_NOTIFICATION命令对应的响应码 |
BR_ACQUIRE_RESULT | - | - |
BR_ATTEMPT_ACQUIRE | - | - |
BR_FINISHED | - | - |
BR_SPAWN_LOOPER:binder驱动已经检测到进程中没有线程等待即将到来的事务。那么当一个进程接收到这条命令时,该进程必须创建一条新的服务线程并注册该线程,在接下来的响应过程会看到何时生成该响应码。
BR_TRANSACTION_COMPLETE:当Client端向Binder驱动发送BC_TRANSACTION命令后,Client会收到BR_TRANSACTION_COMPLETE命令,告知Client端请求命令发送成功;对于Server向Binder驱动发送BC_REPLY命令后,Server端会收BR_TRANSACTION_COMPLETE命令,告知Server端请求回应命令发送成功。
BR_DEAD_REPLY: 当应用层向Binder驱动发送Binder调用时,若Binder应用层的另一个端已经死亡,则驱动回应BR_DEAD_BINDER命令。
BR_FAILED_REPLY: 当应用层向Binder驱动发送Binder调用时,若transaction出错,比如调用的函数号不存在,则驱动回应BR_FAILED_REPLY。