一、发给谁

       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_stack机制_REPLY

在这中间会执行上述代码表示:它发送完数据你回复我的我会放在这个传输栈里边。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;出栈

相关文章: