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中。
这样,客户端整个周期也处理完了。