android进程通讯6,Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析...

这个结构体的含义可以参考浅谈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驱动程序它是守护过程时创建的。0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值