总体发送回复如下:
A进程发送BC_TRANSACTION驱动改为BR_TRANSACTION发给进程B。
B进程发送bc_REPLY 驱动改为BR_REPLY给进程A。
1、发给谁?handle只表明了进程,发给进程 ?还是进程下的某个线程?
一般放在binder_proc的todo链表中,唤醒等待于binder_proc,wait的空闲进程。在porc数据成员中。
对于双向传输,则放在binder_thread.todo里唤醒该线程
情景分析
client发送BC_TRANSACTION时
binder_ioctl
case BINDER_WRITE_READ
binder_thread_write
case BC_TRANSACTION:
binder_transaction
ref = binder_get_ref(proc, tr->target.handle);//根据handle找到ref
target_node = ref->node;//根据ref找到node。
target_proc = target_node->proc;//根据node找到proc
每调用ioctl时会创建thread,即使不是多线程的,那至少也会有一个thread
if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack)//一开始thread->transaction_stack肯定是空的。
{}
else if (!(t->flags & TF_ONE_WAY)) {//这段数据发送之后想得到回复
BUG_ON(t->buffer->async_transaction != 0);
struct binder_transaction *t;
t->to_proc = target_proc;//to_proc=test_server
t->need_reply = 1;
t->from_parent = thread->transaction_stack;//通过t->from_parent放到传输栈中,form=test_client to_thread=NULL
thread->transaction_stack = t;//t表示当前的传输
list_add_tail(&t->work.entry, target_list);//将t放入target_list
target_list = &target_proc->todo;一开始会放入进程的todo链表。
target_wait = &target_proc->wait;
server replay
binder_ioctl case BINDER_WRITE_READ: binder_thread_read thread->transaction_stack == NULL//一开始线程的传输栈为空, w = list_first_entry(&proc->todo, struct binder_work, entry);//因此会从proc中获取数据 t = container_of(w, struct binder_transaction, work);根据w找到其中的binder_transaction t->to_parent = thread->transaction_stack;//通过to parent放到test server的栈中也就是接收者的栈中 t->to_thread = thread;
2、回给谁?无handle表明目的进程,必定在某个地方 记录发送者。
在栈中,记录了来从哪里来,发送到哪里。
service r
binder_ioctl
case BINDER_WRITE_READ
binder_thread_write
case BC_REPLY:
binder_transaction(proc, thread, &tr, cmd == BC_REPLY);
if (reply) {
in_reply_to = thread->transaction_stack;从栈中取出结构体为transaction_stack test server出栈
if (in_reply_to->to_thread != thread) {//如果跟当前线程不等也会出错,当前线程有test_server
copy_from_user//将数据从server中传入发给test_client
if (reply) {
BUG_ON(t->buffer->async_transaction != 0);
binder_pop_transaction(target_thread, in_reply_to);//继续出栈 test client出栈
target_thread->transaction_stack->from_parent;
}



