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

本文详细分析了Android系统中Binder驱动处理异步请求的方式,包括如何接收异步请求,如何将任务放入等待队列,以及在接收回复数据时的处理流程。在异步通信中,如果目标进程已有未完成的异步任务,新的任务会被放入等待队列,待前一个任务完成后执行。同时,介绍了同步和异步通信中binder_transaction_data结构体的生命周期,以及BC_FREE_BUFFER命令在释放资源中的作用。
摘要由CSDN通过智能技术生成

3.5 receive async requet

       接收异步方式发送过来的请求和接收同步方式发来的请求基本一样,不同的是,在将binder_transaction的数据转换到binder_transaction_data之后,将会释放掉binder_transaction数据结构的空间。

由于binder驱动对异步通信做了分流的处理,如果当前目标进程已经有一个异步通信正在处理,那么为了保证同步通信的实时性,所以会将后来发给该进程的异步通信任务放在一个等待队列async_todo中,直到前面那个异步通信任务完成后才会从异步等待队列中取出一个任务放进前次处理异步任务的task的todo队列中去。

(从这里可以看出,如果某个线程正在处理异步任务,当完成的时候发现异步等待队列中还有异步任务需要处理,那么这个等待的异步任务也会被当前这个线程处理,直到这个时间段内的异步任务处理完。隔了段时间之后,如果再有异步任务到来的话,此时驱动可能会分配其他的线程来处理接下来时间段内的异步任务。简单点说,在某线程执行任何一个异步任务未完成之前就已经排到异步等待队列中来的异步任务,都将会由这个线程来执行。)。

不过,我们在binder_thread_read()函数的最后没有看到将异步任务移入线程的todo队列中的动作,这个函数和异步请求接收相关的只有如下地方:

static int binder_thread_read(struct binder_proc *proc,

                           struct binder_thread *thread,

                           void  __user *buffer, int size,

                           signed long *consumed, int non_block)

{

while (1) {

       if (!t) // 非 BINDER_WORK_TRANSACTION 的情况,放弃执行后面的重新循环

              continue;

       …

       if (t->from) {       // 记录发送线程的binder_thread

              … // 同步传输时

       } else { // reply 或者异步传输时

                     tr.sender_pid = 0;

       }

       …

       list_del(&t->work.entry);

       t->buffer->allow_user_free = 1;

       if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) {// 同步传输

              t->to_parent = thread->transaction_stack;

              t->to_thread = thread;

              thread->transaction_stack = t;

       } else { /* 如果收到的是回复数据或者而是异步请求,这里将会释放掉这次单边

传输的binder_transaction结构体,另外所有的传输的binder_buffer结构体空间都是通过上层发送命令BC_FREE_BUFFER来通知binder驱动释放的,因为这部分空间是驱动在管理。*/

                     t->buffer->transaction = NULL;

                     kfree(t);

                     binder_stats_deleted(BINDER_STAT_TRANSACTION);

       }

       break;

}// while(1)

}

那究竟是在哪里移入下一个异步等待任务的呢?其实我们可以想一下,这个binder_thread_read()函数执行完的时候,异步任务还没开始执行,驱动还会将binder_transaction_data结构体传回上层程序,上层程序才真正开始执行异步任务,不过通常上层应用程序在执行完异步任务(其实不只是异步任务,应该是所有类型的任务)被执行完,都应该发送BC_FREE_BUFFER这个命令到binder驱动,通知驱动释放掉一次单边传输时的binder_buffer内存空间。到这里之后,这个异步任务才算得上真正完成。所以我们的前面提到的移入异步任务的事情就是在这个时候做的,请看源码:

int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,void __user *buffer, int size, signed long *consumed)

{

uint32_t cmd;

void __user *ptr = buffer + *consumed;

void __user *end = buffer + size;

      

       while (ptr < end && thread->return_error == BR_OK) {

              …

              switch (cmd) {

                     …

                     case BC_FREE_BUFFER: { // BC_FREE_BUFFER = _IOW('c', 3, int),

// cmd | data_ptr (data_ptr是指binder_buffer.data开始地址)

                    

                     void __user *data_ptr;

                     struct binder_buffer *buffer;

                    

                     if (get_user(data_ptr, (void * __user *)ptr))

                

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值