在Binder IPC通信过程中,进程间通信都要先通过向Binder驱动发送BC_XXX命令,然后Binder 驱动稍做处理后通过对应的BR_XXX将命令转给给目标进程。
如果有返回值,进程也是先将返回结果以BC_REPLY的形式先发给Binder驱动,然后通过驱动以BR_REPLY命令转发。
PS:从Driver发出的命令以BR开始,而发往Driver的命令以BC开头。
Binder1通过BC_Transaction将通信数据发到Binder Driver,Binder Driver通过BR_Transaction将命令转发给Binder2去处理,最后都是通过BC_REPLY的命令将返回结果传回Binder Driver,Binder Driver再通过BR_REPLY将返回结果转发给Binder1。
相关函数binder_transaction(...)
先看BC_TRANSACTION命令的处理过程(binder1->Driver)。
首先,第一步,Binder驱动判断当前命令接收方是Service Manager还是普通的Server端,判断依据是tr->target.handle.if (tr->target.handle == 0) 表示该命令是发送特殊结点,即Service Manager,而else 针对一般情况,我们需要判断Binder驱动中有没有对应的结点引用,正常情况下应该是能够找到handle对应的Binder结点引用的。通过结点引用,我们就可以定位到处理命令的Binder结点(实体结点)。总之,我们要先知道这个命令是要发往何处。
else {
if (tr->target.handle) {
struct binder_ref *ref;
ref = binder_get_ref(proc, tr->target.handle);
if (ref == NULL) {
binder_user_error("%d:%d got transaction to invalid handle\n",
proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
goto err_invalid_target_handle;
}
target_node = ref->node;
} else {
target_node = binder_context_mgr_node;
if (target_node == NULL) {
return_error = BR_DEAD_REPLY;
goto err_no_context_mgr_node;
}
}
有了Binder结点的信息,我们就可以知道它所处的进程了。
target_proc = target_node->proc;
if (target_proc == NULL) {
return_error = BR_DEAD_REPLY;
goto err_dead_binder;
}
然后会有一个安全检查,主要是判断这通信双方所处的进程能不能传输数据。
if (security_binder_transaction(proc->tsk, target_proc->tsk) < 0) {
return_error = BR_FAILED_REPLY;
goto err_invalid_target_handle;
}
接下来,对于同步通信(即two way),且当前transaction_stack链表不为空的话(也即表示当前线程至少存在一个通信会话),