一、发给谁
handle只表明了进程是发给进程,还是发给这个进程的某个线程。一般放在proc .todo中,唤醒等待于proc .wait的空闲线程。特殊:对于双向传输(也是用transaction_stack来判断)则放在binder_thread .todo 然后唤醒该线程
二、回复给谁
无handle,必定在某个地方(指transaction_stack)有记录谁发给你你就回复给谁
三、情景分析
client->server
发bc_transaction 收br_transaction
发bc_reply
收br_reply
一开始双向传输肯定为空所以执行下面代码
if (target_thread) {
e->to_thread = target_thread->pid;
target_list = &target_thread->todo;
target_wait = &target_thread->wait;
} else {
target_list = &target_proc->todo;
target_wait = &target_proc->wait;
}
执行else分支,即数据放到todo链表,唤醒等待在该进程下的线程。
else if (!(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;//////////////链表操作client里的binder_thread里的transaction_stack指向一个传输结构,然后这个传输结构的from_parent指向原来的值。
在这中间会执行上述代码表示:它发送完数据你回复我的我会放在这个传输栈里边。binder_transaction的from_parent指向当前线程的transaction_stack传输栈。
以上都是在binder_transaction函数实现的。之后唤醒等待在serverproc的线程
轮到binder_thread_read函数执行
wait_for_proc_work = thread->transaction_stack == NULL &&
list_empty(&thread->todo);这transaction_stack肯定为空
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)/////////////执行这个分支因为只有双向传输时才往thread的todo链表里写现在它为空。
再往下
w = list_first_entry(&proc->todo, struct binder_work, entry);
if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) {
t->to_parent = thread->transaction_stack;////////表示我i这个t要给到当前线程的栈里
t->to_thread = thread;
thread->transaction_stack = t;
}
得到的是 BR_TRANSACTION进行入栈
1、从server的binder_proc的todo链表中取出数据处理
2、入栈 对于同一个数据结构binder_transaction结构体,通过to_parent放到当前线程的栈里即接收者的栈中,通过from_parent放入发送者的栈中。
进入用户态后在进入binder_transation函数
RC_REPLY
回复给谁
in_reply_to = thread->transaction_stack;这个结构体里有要回复的.from是client
if (in_reply_to->to_thread != thread) {判断取出的binder_stack结构体的to_thread是否等于现在的线程
thread->transaction_stack = in_reply_to->to_parent;出栈
然后copy_from_user
然后target_thread->transaction_stack =
target_thread->transaction_stack->from_parent;出栈