这个结构体的含义可以参考浅谈Service Manager成为Android进程间通信(IPC)机制Binder守护进程之路一文。这里首先是通过copy_from_user函数把用户传进来的参数的内容拷贝到本地变量bwr中。
从上面的调用过程,我们知道,这里bwr.write_size是大于0的,因此进入到binder_thread_write函数中,我们只关注BC_TRANSACTION相关的逻辑:
int
binder_thread_write(structbinder_proc *proc,structbinder_thread *thread,
void__user *buffer,intsize,signedlong*consumed)
{
uint32_t cmd;
void__user *ptr = buffer + *consumed;
void__user *end = buffer + size;
while(ptr return_error == BR_OK) {
if(get_user(cmd, (uint32_t __user *)ptr))
return-EFAULT;
ptr +=sizeof(uint32_t);
if(_IOC_NR(cmd)
binder_stats.bc[_IOC_NR(cmd)]++;
proc->stats.bc[_IOC_NR(cmd)]++;
thread->stats.bc[_IOC_NR(cmd)]++;
}
switch(cmd) {
......
caseBC_TRANSACTION:
caseBC_REPLY: {
structbinder_transaction_data tr;
if(copy_from_user(&tr, ptr,sizeof(tr)))
return-EFAULT;
ptr +=sizeof(tr);
binder_transaction(proc,thread, &tr, cmd == BC_REPLY);
break;
}
......
default:
printk(KERN_ERR"binder: %d:%d unknown command %d\n", proc->pid,thread->pid, cmd);
return-EINVAL;
}
*consumed = ptr - buffer;
}
return0;
}
这里再次把用户传出来的参数拷贝到本地变量tr中,tr的类型为struct binder_transaction_data,这个就是前面我们在IPCThreadState::writeTransactionData写入的内容了。
接着进入到binder_transaction函数中,不相关的代码我们忽略掉:
staticvoid
binder_transaction(structbinder_proc *proc,structbinder_thread *thread,
structbinder_transaction_data *tr,intreply)
{
structbinder_transaction *t;
structbinder_work *tcomplete;
size_t*offp, *off_end;
structbinder_proc *target_proc;
structbinder_thread *target_thread = NULL;
structbinder_node *target_node = NULL;
structlist_head *target_list;
wait_queue_head_t *target_wait;
structbinder_transaction *in_reply_to = NULL;
structbinder_transaction_log_entry *e;
uint32_t return_error;
.......
if(reply) {
......
}else{
if(tr->target.handle) {
......
}else{
target_node = binder_context_mgr_node;
if(target_node == NULL) {
return_error = BR_DEAD_REPLY;
gotoerr_no_context_mgr_node;
}
}
......
target_proc = target_node->proc;
if(target_proc == NULL) {
return_error = BR_DEAD_REPLY;
gotoerr_dead_binder;
}
if(!(tr->flags & TF_ONE_WAY) &&thread->transaction_stack) {
......
}
}
if(target_thread) {
......
}else{
target_list = &target_proc->todo;
target_wait = &target_proc->wait;
}
......
/* TODO: reuse incoming transaction for reply */
t = kzalloc(sizeof(*t), GFP_KERNEL);
if(t == NULL) {
return_error = BR_FAILED_REPLY;
gotoerr_alloc_t_failed;
}
binder_stats.obj_created[BINDER_STAT_TRANSACTION]++;
tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
if(tcomplete == NULL) {
return_error = BR_FAILED_REPLY;
gotoerr_alloc_tcomplete_failed;
}
binder_stats.obj_created[BINDER_STAT_TRANSACTION_COMPLETE]++;
t->debug_id = ++binder_last_id;
......
if(!reply && !(tr->flags & TF_ONE_WAY))
t->from =thread;
else
t->from = NULL;
t->sender_euid = proc->tsk->cred->euid;
t->to_proc = target_proc;
t->to_thread = target_thread;
t->code = tr->code;
t->flags = tr->flags;
t->priority = task_nice(current);
t->buffer = binder_alloc_buf(target_proc, tr->data_size,
tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));
if(t->buffer == NULL) {
return_error = BR_FAILED_REPLY;
gotoerr_binder_alloc_buf_failed;
}
t->buffer->allow_user_free = 0;
t->buffer->debug_id = t->debug_id;
t->buffer->transaction = t;
t->buffer->target_node = target_node;
if(target_node)
binder_inc_node(target_node, 1, 0, NULL);
offp = (size_t*)(t->buffer->data + ALIGN(tr->data_size,sizeof(void*)));
if(copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) {
......
return_error = BR_FAILED_REPLY;
gotoerr_copy_data_failed;
}
......
if(reply) {
......
}elseif(!(t->flags & TF_ONE_WAY)) {
BUG_ON(t->buffer->async_transaction != 0);
t->need_reply = 1;
t->from_parent =thread->transaction_stack;
thread->transaction_stack = t;
}else{
......
}
t->work.type = BINDER_WORK_TRANSACTION;
list_add_tail(&t->work.entry, target_list);
tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
list_add_tail(&tcomplete->entry, &thread->todo);
if(target_wait)
wake_up_interruptible(target_wait);
return;
......
}
注意,这里的参数reply = 0,表示这是一个BC_TRANSACTION命令。
前面我们提到,传给驱动程序的handle值为0,即这里的tr->target.handle = 0,表示请求的目标Binder对象是Service Manager,因此有:
target_node = binder_context_mgr_node;
target_proc = target_node->proc;
target_list = &target_proc->todo;
target_wait = &target_proc->wait;
其中binder_context_mgr_node是在Service Manager通知Binder驱动程序它是守护过程时创建的。