您的位置:首页 > 移动开发 > Android开发

android binder机制,注册系统服务---结果返回

2017-06-12 22:12 246 查看

5结果返回

用户态的Servicemanager进程发送的是BINDER_WRITE_READ命令,需要处理返回的BC_REPLY命令。

并且只有写操作,没有读操作,即read_size为0。

5.1 servicemanager进程binder驱动

1,首先binder驱动的binder_ioctl方法处理BINDER_WRITE_READ命令,前面已经论述了,在此就不赘述。

2, binder_ioctl方法调用binder_thread_write方法处理BC_REPLY命令

当然是和BC_TRANSACTION命令一起处理的,只是调用binder_transaction时最后一个参数不一样,

case BC_TRANSACTION:
case BC_REPLY: {
struct binder_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;
}


binder_transaction以及以后的方法上面都论述过,在此不再论述了。关键代码如下,

tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
list_add_tail(&tcomplete->entry, &thread->todo);
if (target_wait)
wake_up_interruptible(target_wait);
return;

此时发送的命令是BINDER_WORK_TRANSACTION_COMPLETE,

然后唤醒客户端的等待线程,执行binder_thread_read方法。

通俗的讲,原理如下,

1,顾客告诉厨师需要的菜之后就去睡觉了。

2,厨师做好菜之后就将客户叫醒,该吃饭了。

这样, servicemanager进程一个周期的消息就处理完了,返回到binder_loop方法

for (;;) {
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (uintptr_t) readbuf;
// 读取驱动的命令
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);

if (res < 0) {
ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
break;
}
// 解析命令
res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
if (res == 0) {
ALOGE("binder_loop: unexpected reply?!\n");
break;
}

接着调用ioctl方法进入内核态,调用binder_thread_read方法,进入等待状态,等待下一个客户进程的请求,

如此这样循环往复,生生不息。

好了, 对于注册消息,servicemanager进程到此就分析完了。

5.2 客户进程binder驱动

绕了这么一大圈,又回到了客户端进程, binder驱动的binder_thread_read方法对

BINDER_WORK_TRANSACTION_COMPLETE消息处理如下,

case BINDER_WORK_TRANSACTION_COMPLETE: {
cmd = BR_TRANSACTION_COMPLETE;
if (put_user(cmd, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);

binder_stat_br(proc, thread, cmd);
binder_debug(BINDER_DEBUG_TRANSACTION_COMPLETE,
"%d:%d BR_TRANSACTION_COMPLETE\n",
proc->pid, thread->pid);

list_del(&w->entry);
kfree(w);
binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
} break;
•••
tr.target.ptr = 0;
tr.cookie = 0;
cmd = BR_REPLY;

这样,内核态返回给servicemanager进程用户态的命令是BR_TRANSACTION_COMPLETE。

发送给客户端用户态的命令是BR_REPLY。

 

用户态将数据从内核态复制到用户态,其他的处理就不多说了。

binder_thread_read方法处理完成之后,返回到binder_ioctl方法,然后返回到用户态的talkWithDriver方法, 

最后返回到waitForResponse方法。

5.3 客户进程

waitForResponse方法对BR_REPLY命令处理如下,

case BR_REPLY:
{
binder_transaction_data tr;
err = mIn.read(&tr, sizeof(tr));
ALOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");
if (err != NO_ERROR) goto finish;

if (reply) {
if ((tr.flags & TF_STATUS_CODE) == 0) {
reply->ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t),
freeBuffer, this);
} else {
err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);
freeBuffer(NULL,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), this);
}
} else {
freeBuffer(NULL,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), this);
continue;
}
}
goto finish;

这样客户进程就得到了目标进程ServiceManager发送过来的服务注册结果了,结果保存在reply中。

这样,客户端整个周期也处理完了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息