接着创建一个待完成事项tcomplete,它的类型为struct binder_work,这是等一会要保存在当前线程的todo队列去的,表示当前线程有一个待完成的事务。紧跟着创建一个待处理事务t,它的类型为struct binder_transaction,这是等一会要存在到Service Manager的todo队列去的,表示Service Manager当前有一个事务需要处理。同时,这个待处理事务t也要存放在当前线程的待完成事务transaction_stack列表中去:
t->from_parent = thread->transaction_stack; thread->transaction_stack = t;
这样表明当前线程还有事务要处理。继续往下看,就是分别把tcomplete和t放在当前线程thread和Service Manager进程的todo队列去了:
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); 最后,Service Manager有事情可做了,就要唤醒它了:
wake_up_interruptible(target_wait);
前面我们提到,此时Service Manager正在等待Client的请求,也就是Service Manager此时正在进入到Binder驱动程序的binder_thread_read函数中,并且休眠在target->wait上,具体参考浅谈Service Manager成为Android进程间通信(IPC)机制Binder守护进程之路一文。
这里,我们暂时忽略Service Manager被唤醒之后的情景,继续看当前线程的执行。
函数binder_transaction执行完成之后,就一路返回到binder_ioctl函数里去了。函数binder_ioctl从binder_thread_write函数调用处返回后,发现bwr.read_size大于0,于是就进入到binder_thread_read函数去了:
static int binder_thread_read(struct binder_proc *proc, struct binder_thread *thread, void __user *buffer, int size, signed long *consumed, int non_block) { void __user *ptr = buffer + *consumed; void __user *end = buffer + size; int ret = 0; int wait_for_proc_work; if (*consumed == 0) { if (put_user(BR_NOOP, (uint32_t __user *)ptr)) return -EFAULT; ptr += sizeof(uint32_t); } retry: wait_for_proc_work = thread->transaction_stack == NULL && list_empty(&thread->todo); ...... if (wait_for_proc_work) { ...... } else { if (non_block) { if (!binder_has_thread_work(thread)) ret = -EAGAIN; } else ret = wait_event_interruptible(thread->wait, binder_has_thread_work(thread)); } ...... while (1) { uint32_t cmd; struct binder_transaction_data tr; struct binder_work *w; struct binder_transaction *t = NULL; if (!list_empty(&thread->todo)) w = list_first_entry(&thread->todo, struct binder_work, entry); else if (!list_empty(&proc->todo) && wait_for_proc_work) w = list_first_entry(&proc->todo, struct binder_work, entry); else { if (ptr - buffer == 4 && !(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN)) /* no data added */ goto retry; break; } if (end - ptr < sizeof(tr) + 4) break; switch (w->type) { ...... 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); if (binder_debug_mask & BINDER_DEBUG_TRANSACTION_COMPLETE) printk(KERN_INFO "binder: %d:%d BR_TRANSACTION_COMPLETE\n", proc->pid, thread->pid); list_del(&w->entry); kfree(w); binder_stats.obj_deleted[BINDER_STAT_TRANSACTION_COMPLETE]++; } break; ...... } if (!t) continue; ...... } done: ...... return 0; }
函数首先是写入一个操作码BR_NOOP到用户传进来的缓冲区中去。回忆一下上面的binder_transaction函数,这里的thread->transaction_stack != NULL,并且thread->todo也不为空,所以线程不会进入休眠状态。
进入while循环中,首先是从thread->todo队列中取回待处理事项w,w的类型为BINDER_WORK_TRANSACTION_COMPLETE,这也是在binder_transaction函数里面设置的。对BINDER_WORK_TRANSACTION_COMPLETE的处理也很简单,只是把一个操作码BR_TRANSACTION_COMPLETE写回到用户传进来的缓冲区中去。这时候,用户传进来的缓冲区就包含两个操作码了,分别是BR_NOOP和BINDER_WORK_TRANSACTION_COMPLETE。
binder_thread_read执行完之后,返回到binder_ioctl函数中,将操作结果写回到用户空间中去:
if (copy_to_user(ubuf, &bwr, sizeof(bwr))) { ret = -EFAULT; goto err; } 最后就返回到IPCThreadState::talkWithDriver函数中了。
IPCThreadState::talkWithDriver函数从下面语句:
ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) 返回后,首先是清空之前写入Binder驱动程序的内容:
if (bwr.write_consumed > 0) { if (bwr.write_consumed < (ssize_t)mOut.dataSize()) mOut.remove(0, bwr.write_consumed); else mOut.setDataSize(0); } 接着是设置从Binder驱动程序读取的内容:
if (bwr.read_consumed > 0) { mIn.setDataSize(bwr.read_consumed); mIn.setDataPosition(0); } 然后就返回到IPCThreadState::waitForResponse去了。IPCThreadState::waitForResponse函数的处理也很简单,就是处理刚才从Binder驱动程序读入内容了。从前面的分析中,我们知道,从Binder驱动程序读入的内容就是两个整数了,分别是BR_NOOP和BR_TRANSACTION_COMPLETE。对BR_NOOP的处理很简单,正如它的名字所示,什么也不做;而对BR_TRANSACTION_COMPLETE的处理,就分情况了,如果这个请求是异步的,那个整个BC_TRANSACTION操作就完成了,如果这个请求是同步的,即要等待回复的,也就是reply不为空,那么还要继续通过IPCThreadState::talkWithDriver进入到Binder驱动程序中去等待BC_TRANSACTION操作的处理结果。