binder驱动-交互时的传输实现(三)

3.3 transaction async request

       对于异步传输,在上层空间传下来的数据结构binder_transcation_data中的flags域中可以体现出来,也就是flags的TF_ONE_WAY位为1,就表示需要异步传输,不需要等待回复数据。

       其实异步和同步传输在发送请求的过程绝大多数是一样的,这里就不再重复,本小节描述一下关于异步传输独有的地方即可。

       关键在函数调用binder_transaction(proc, thread, &tr, cmd == BC_REPLY)中体现了不同:

static void binder_transaction(struct binder_proc *proc,

                            struct binder_thread *thread,

                            struct binder_transaction_data *tr, int reply)

{

       if (reply) { // 发送的是回复数据

              …

}else { // 发送的是请求数据

              …

              if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {

                     … // 同步传输的优化

              }

       }

       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;

       }

       …

       if (!reply && !(tr->flags & TF_ONE_WAY))

              … // 发送同步非回复数据

       else

              t->from = NULL; /* 如果是BC_REPLY或者是异步传输,这里不需要记录和返回信息相关的东西。*/

       …

       t->buffer = binder_alloc_buf(target_proc, tr->data_size,

                            tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));

       /* 最后一个参数只有在非回复并且是异步的情况下才会为1,这个值会记录在所分配

的binder_buffer.async_transaction中来表示当前的buffer用在异步传输中还是同步传输中。*/

       …  // flat_binder_object结构体处理

       if (reply) {    // 发送的是回复数据

              …

       }else if (!(t->flags & TF_ONE_WAY)) { // 同步发送请求

              …

       }else { // 异步发送请求

              BUG_ON(target_node == NULL);// 异步传输时目标一定要明确

              BUG_ON(t->buffer->async_transaction != 1); // 前面提到的重要标志

              // 下面是对异步通讯的分流处理

       if (target_node->has_async_transaction) {/* 如果目标task仍然还有一

个异步需要处理的话,该标志为1。*/

                     target_list = &target_node->async_todo;/* 将当前的这个的异步传输任

务转入目标进程binder_node的异步等待队列async_todo中。*/

                     target_wait = NULL;

              } else

                     target_node->has_async_transaction = 1;

                     // 否则,将该标志置1,表明当前有一个异步交互正在处理。

       } // else

       t->work.type = BINDER_WORK_TRANSACTION;

       list_add_tail(&t->work.entry, target_list); /* 将binder_work加入目标任务队

列中: async_todo。 */

       tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;

       list_add_tail(&tcomplete->entry, &thread->todo);/* 发送端binder_work加入当

前线程的todo队列中,binder驱动通知发送端,数据已经成功发送出去了。*/

       …

       if (target_wait) {

              …

wake_up_interruptible(target_wait);  // target_wait == NULL

       }

       …

}

       对于异步发送请求来说,到这里结束之后,驱动中已经准备好了相应的binder_transaction结构体,只不过极有可能将这个结构体通过其中的binder_work域挂到了目标进程的binder_node.async_todo队列中,直到target_node->has_async_transaction标志为0。接着如果运气好的话,才有可能将binder_transaction移动到目标进程的全局任务队列binder_node.todo中,这时binder驱动就会给他找一个空闲线程来处理这个请求数据包。

 

3.4 receive request

       接收端的task也是利用ioctl()进行读操作的,前面列出的struct binder_write_read结构体中如果有包含读取数据的buffer和预备读取大小,那么在write完该传输的数据之后就会进行read的操作,如下:(整理下思路,以下所讨论的内容均属于另一个进程的某个task,和前面传输部分属于不同的task,所以调用ioctl的时候,所描述的当前task也是接收端的,而非发送端。)

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){ </

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值