Open cyrushine opened 1 year ago
https://www.jianshu.com/p/4be292a51388
static int binder_thread_read(struct binder_proc *proc, struct binder_thread *thread, binder_uintptr_t binder_buffer, size_t size, binder_size_t *consumed, int non_block) { void __user *buffer = (void __user *)(uintptr_t)binder_buffer; void __user *ptr = buffer + *consumed; void __user *end = buffer + size; int ret = 0; int wait_for_proc_work; if (*consumed == 0) {/*当前的写入位置为bwr.read_buffer的起始位置,先写入一个BR_NOOP命令到read_buffer中,该命令在用户态是一个空操作,什么也不做,主要意义应该是在输出日志等*/ if (put_user(BR_NOOP, (uint32_t __user *)ptr)) return -EFAULT; ptr += sizeof(uint32_t); } retry: /*如果线程事务栈和todo队列都为空,说明此时没有要当前线程处理的任务,将增加空闲线程的计数器(即将wait_for_proc_work设为1),让线程等待在**进程**的wait队列上*/ wait_for_proc_work = thread->transaction_stack == NULL && list_empty(&thread->todo); if (thread->return_error != BR_OK && ptr < end) {/*之前在binder_transaction或者binder death时发生了错误*/ if (thread->return_error2 != BR_OK) { /*发送reply时发生了错误,将错误返回给进程用户态*/ if (put_user(thread->return_error2, (uint32_t __user *)ptr)) return -EFAULT; ptr += sizeof(uint32_t); binder_stat_br(proc, thread, thread->return_error2); if (ptr == end) goto done; thread->return_error2 = BR_OK; } if (put_user(thread->return_error, (uint32_t __user *)ptr)) return -EFAULT; ptr += sizeof(uint32_t); binder_stat_br(proc, thread, thread->return_error); thread->return_error = BR_OK; goto done; } /*即将进入睡眠等待区,这会导致进程/线程进入阻塞状态,先将线程状态改为BINDER_LOOPER_STATE_WAITING*/ thread->looper |= **BINDER_LOOPER_STATE_WAITING**; if (wait_for_proc_work)/*进程/线程没事需要处理*/ proc->ready_threads++;/*空闲线程数+1*/ /*线程/进程将可能进入阻塞等待状态,先释放锁,这个锁是在binder_ioctl开始执行就拿了*/ binder_unlock(__func__); trace_binder_wait_for_work(wait_for_proc_work, !!thread->transaction_stack, !list_empty(&thread->todo)); if (wait_for_proc_work) {/*线程暂时没有工作要处理,进程/线程需要等待*/ if (!(thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED))) { /* 线程还未进入binder循环,输出错误信息,并阻塞直到binder_stop_on_user_error小于2*/ binder_user_error("%d:%d ERROR: Thread waiting for process work before calling BC_REGISTER_LOOPER or BC_ENTER_LOOPER (state %x)\n", proc->pid, thread->pid, thread->looper); wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); } binder_set_nice(proc->default_priority); if (non_block) {/*设置了非阻塞标识*/ if (!binder_has_proc_work(proc, thread)) /*检查当前进程是否有工作待处理,如果没有就将返回值设为-EAGAIN,以便用户进程稍后重试*/ ret = -**EAGAIN**; } else/*如果是阻塞的读操作,则让进程阻塞在proc的wait队列上,直到binder_has_proc_work(thread)为true,即进程有工作待处理*/ ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread)); } else {/**/ if (non_block) {/*读操作设置了非阻塞标识*/ if (!binder_has_thread_work(thread)) /*检查当前线程是否有工作待处理,如果没有就将返回值设为-EAGAIN,以便用户进程稍后重试*/ ret = -**EAGAIN**; } else/*如果是阻塞的读操作,则让线程阻塞在thread的wait队列上,直到binder_has_thread_work(thread)为true,即线程有工作待处理*/ ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread)); } /*运行到这里,要么是线程/进程没有工作待处理,但是讲返回值ret设置成了-EAGAIN;要么是线程/进程已经有工作待处理了*/ binder_lock(__func__); /*重新获取锁*/ if (wait_for_proc_work)/*之前进入了等待操作,线程被挂起了*/ proc->ready_threads--;/*空闲线程数减1*/ thread->looper &= **~BINDER_LOOPER_STATE_WAITING**;/*移除线程等待标志位*/ /* We cannot return -ERESTARTSYS here. This code is called * after binder_thread_write() has already interpreted the * input buffer. A restart will result in a doubled set of * commands. Just return success, having consumed zero * bytes. */ if (ret) return ret == -ERESTARTSYS ? 0 : ret; /*开始循环处理thread/proc的todo队列上的每一个binder_work*/ while (1) { uint32_t cmd; struct binder_transaction_data tr; struct binder_work *w; struct binder_transaction *t = NULL; /*取出一个binder work来处理*/ 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) {/*进程的待处理列表不为空,且睡眠等待前线程的`todo`队列和事务栈都为空*/ w = list_first_entry(&proc->todo, struct binder_work, /*从进程的待处理列表的队头中取出一项工作处理*/ entry); } else { /* no data added */ if (ptr - buffer == 4 && !(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN)) goto retry; break; } if (end - ptr < sizeof(tr) + 4) break; switch (w->type) { case **BINDER_WORK_TRANSACTION**: {/*要处理的是一个事务(Binder请求)*/ /*根据binder_work在binder_transaction的偏移计算出binder_transaction的地址*/ t = container_of(w, struct binder_transaction, work); } break; case **BINDER_WORK_TRANSACTION_COMPLETE**: { /*TRANSACTION或者REPLY发送完成消息,通过给进程发送BR_TRANSACTION_COMPLETE告知*/ cmd = BR_TRANSACTION_COMPLETE; if (put_user(cmd, (uint32_t __user *)ptr))/*发送给用户进程*/ return -EFAULT; ptr += sizeof(uint32_t); binder_stat_br(proc, thread, cmd);/*更新统计数据*/ binder_debug(BINDER_DEBUG_TRANSACTION_COMPLETE, "%d:%d BR_TRANSACTION_COMPLETE\n", proc->pid, thread->pid); list_del(&w->entry);/*从todo队列中移除*/ kfree(w); /*释放在binder_thread_write在处理BC_TRANSACTION命令时在binder_transaction中申请的binder_work*/ binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); /*更新BINDER_STAT_TRANSACTION_COMPLETE统计数据*/ } break; case **BINDER_WORK_NODE**: {/*取出的binder_work是一个binder_node*/ struct binder_node *node = container_of(w, struct binder_node, work); /*根据偏移计算出binder_node的地址*/ uint32_t cmd = BR_NOOP; const char *cmd_name; int strong = node->internal_strong_refs || node->local_strong_refs; int weak = !hlist_empty(&node->refs) || node->local_weak_refs || strong; if (weak && !node->has_weak_ref) {/*弱引用计数不为0,但是弱引用标志位为0*/ cmd = BR_INCREFS; /*发送BR_INCREFS命令给进程用户态,让其增加弱引用计数*/ cmd_name = "BR_INCREFS"; node->has_weak_ref = 1; /*设置弱引用标志位*/ node->pending_weak_ref = 1; /*设置pengding标志位,表示(进程用户态)有未处理的弱引用增加命令*/ node->local_weak_refs++; /*增加本地弱引用计数器*/ } else if (strong && !node->has_strong_ref) {/*强引用计数不为0,但是强引用标志位为0*/ cmd = BR_ACQUIRE; /*发送BR_ACQUIRE命令给进程,让其增加强引用计数*/ cmd_name = "BR_ACQUIRE"; node->has_strong_ref = 1; /*设置强引用标志位*/ node->pending_strong_ref = 1; /*设置pengding标志位,表示(进程用户态)有未处理的强引用增加命令*/ node->local_strong_refs++; /*增加本地强引用计数器*/ } else if (!strong && node->has_strong_ref) {/*强引用计数为0,但是强引用标志位不为0*/ cmd = BR_RELEASE; cmd_name = "BR_RELEASE"; node->has_strong_ref = 0; } else if (!weak && node->has_weak_ref) {/*弱引用计数为0,但是弱引用标志位不为0*/ cmd = BR_DECREFS; cmd_name = "BR_DECREFS"; node->has_weak_ref = 0; } if (cmd != BR_NOOP) {/*有引用计数相关的命令需要处理*/ /*将命令先发送给进程用户态*/ if (put_user(cmd, (uint32_t __user *)ptr)) return -EFAULT; ptr += sizeof(uint32_t); /*BBinder的引用计数器的地址发送给进程的用户态地址空间read_buffer*/ if (put_user(node->ptr, (binder_uintptr_t __user *)ptr)) return -EFAULT; ptr += sizeof(binder_uintptr_t); /*BBinder的地址发送给进程*/ if (put_user(node->cookie, (binder_uintptr_t __user *)ptr)) return -EFAULT; ptr += sizeof(binder_uintptr_t); /*更新统计数据*/ binder_stat_br(proc, thread, cmd); binder_debug(BINDER_DEBUG_USER_REFS, "%d:%d %s %d u%016llx c%016llx\n", proc->pid, thread->pid, cmd_name, node->debug_id, (u64)node->ptr, (u64)node->cookie); } else {/*不需要增加/减少binder_node的强/弱引用计数*/ list_del_init(&w->entry);/*从todo队列中移出*/ if (!weak && !strong) {/*binder_node的强弱引用计数都为0,释放该binder_node*/ binder_debug(BINDER_DEBUG_INTERNAL_REFS, "%d:%d node %d u%016llx c%016llx deleted\n", proc->pid, thread->pid, node->debug_id, (u64)node->ptr, (u64)node->cookie); rb_erase(&node->rb_node, &proc->nodes);/*从proc->nodes红黑树中移除*/ kfree(node);/*释放binder_node所占内存空间*/ binder_stats_deleted(BINDER_STAT_NODE);/*更新统计数据*/ } else { binder_debug(BINDER_DEBUG_INTERNAL_REFS, "%d:%d node %d u%016llx c%016llx state unchanged\n", proc->pid, thread->pid, node->debug_id, (u64)node->ptr, (u64)node->cookie); } } } break; /*binder service死亡相关的几个命令处理*/ case **BINDER_WORK_DEAD_BINDER**: case **BINDER_WORK_DEAD_BINDER_AND_CLEAR**: case **BINDER_WORK_CLEAR_DEATH_NOTIFICATION**: { struct binder_ref_death *death; uint32_t cmd; death = container_of(w, struct binder_ref_death, work);/*根据偏移计算出包含它的binder_ref_death对象的地址*/ if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)/*死亡通知清理完毕的消息*/ cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE;/*回复命令设为BR_CLEAR_DEATH_NOTIFICATION,告知用户进程清除通知完毕的相关处理已完成*/ else cmd = BR_DEAD_BINDER;/*告诉用户进程,binder service已经死亡*/ if (put_user(cmd, (uint32_t __user *)ptr)) /*将命令发送给用户*/ return -EFAULT; ptr += sizeof(uint32_t); if (put_user(death->cookie, (binder_uintptr_t __user *)ptr))/*客户端对象(BpBinder)对应的地址发送到用户进程*/ return -EFAULT; ptr += sizeof(binder_uintptr_t); binder_stat_br(proc, thread, cmd); binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, "%d:%d %s %016llx\n", proc->pid, thread->pid, cmd == BR_DEAD_BINDER ? "BR_DEAD_BINDER" : "BR_CLEAR_DEATH_NOTIFICATION_DONE", (u64)death->cookie); if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) { list_del(&w->entry); kfree(death); binder_stats_deleted(BINDER_STAT_DEATH); } else /*`BINDER_WORK_DEAD_BINDER`和`BINDER_WORK_DEAD_BINDER_AND_CLEAR`移到proc->delivered_deat队列*/ list_move(&w->entry, &proc->delivered_death); if (cmd == BR_DEAD_BINDER) goto done; /* DEAD_BINDER notifications can cause transactions */ } break; }//end of switch /*当binder_work的类型是BINDER_WORK_TRANSACTION时,t不为NULL*/ if (!t) continue; /*接下来开始处理**TRANSACTION**,将binder_transaction转换为进程用户态使用的binder_transaction_data*/ BUG_ON(t->buffer == NULL); /* 在binder_transaction章节中我们知道,当binder客户端向binder服务端发送请求时, * target_node为binder服务端的binder_node地址,如果是binder服务端回复客户端,则target_node为NULL。 */ if (t->buffer->target_node) {/*Client->Server的binder请求*/ struct binder_node *target_node = t->buffer->target_node; /*将引用计数器地址及BBinder地址写入transaction data中, 即将struct binder_transaction转化为进程用户态可处理struct binder_transaction_data结构体*/ tr.target.ptr = target_node->ptr; tr.cookie = target_node->cookie; /*设置线程优先级信息*/ t->saved_priority = task_nice(current); if (t->priority < target_node->min_priority && !(t->flags & TF_ONE_WAY)) binder_set_nice(t->priority); else if (!(t->flags & TF_ONE_WAY) || t->saved_priority > target_node->min_priority) binder_set_nice(target_node->min_priority); cmd = BR_TRANSACTION; } else {/*Client->Server的binder请求的回复*/ /* 将引用计数器地址及BBinder地址从transaction data清空, * 因为Client无法从地址中获取相应的对象,这个地址只有在服务端的进程的地址空间才有效。 */ tr.target.ptr = 0; tr.cookie = 0; cmd = BR_REPLY; } tr.code = t->code;/*设置transacton的业务代码,一种代码对应一种binder server提供的服务*/ tr.flags = t->flags;/*设置transacton的标识位*/ tr.sender_euid = from_kuid(current_user_ns(), t->sender_euid);/*请求线程的有eudi*/ /*设置发送端进程id*/ if (t->from) { struct task_struct *sender = t->from->proc->tsk; tr.sender_pid = task_tgid_nr_ns(sender, task_active_pid_ns(current)); } else { tr.sender_pid = 0; } /*数据相关信息*/ tr.data_size = t->buffer->data_size; /*数据大小*/ tr.offsets_size = t->buffer->offsets_size; /*offsets区大小*/ /*将binder_transaction_data中数据指针直接转换成binder_buffer映射到用户态地址,**这样就无需再从内核态拷贝到用户态的操作了***/ tr.**data.ptr.buffer** = (binder_uintptr_t)( (uintptr_t)t->buffer->data + proc->user_buffer_offset); /*将binder_transaction_data的offset区地址设置为binder_buffer中相应的offset区用户态地址*/ tr.data.ptr.offsets = tr.data.ptr.buffer + ALIGN(t->buffer->data_size, sizeof(void *)); if (**put_user(cmd, (uint32_t __user *)ptr**))/*将BINDER_TRANACTION或者BINDER_REPLEY命令发送到进程用户态*/ return -EFAULT; ptr += sizeof(uint32_t); if (copy_to_user(ptr, &tr, sizeof(tr)))/*将binder_transaction_data拷贝到进程用户态*/ return -EFAULT; ptr += sizeof(tr); trace_binder_transaction_received(t); binder_stat_br(proc, thread, cmd);/*更新统计数据*/ binder_debug(BINDER_DEBUG_TRANSACTION, "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %016llx-%016llx\n", proc->pid, thread->pid, (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" : "BR_REPLY", t->debug_id, t->from ? t->from->proc->pid : 0, t->from ? t->from->pid : 0, cmd, t->buffer->data_size, t->buffer->offsets_size, (u64)tr.data.ptr.buffer, (u64)tr.data.ptr.offsets); list_del(&t->work.entry);/*从todo队列中移除*/ t->buffer->allow_user_free = 1; /*因为这块地址已经交给进程用户态使用了,因此运行进程释放该段地址空间*/ if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) {/*BINDER_TRANSACTION*/ /*加入事务栈*/ t->to_parent = thread->transaction_stack; t->to_thread = thread; thread->transaction_stack = t; } else {/*BINDER_REPLY*/ /*一次binder通信已完成,释放binder_transaction*/ t->buffer->transaction = NULL; kfree(t); binder_stats_deleted(BINDER_STAT_TRANSACTION);/*更新被删除相关的统计数据*/ } **break;/*处理完一个BINDER_WORK_TRANSACTION,就退出循环。说明对于BINDER_WORK_TRANSACTION每次至多只处理一个*/** }//end while done: *consumed = ptr - buffer;/*发送给用户态的字节数*/ if (proc->requested_threads + proc->ready_threads == 0 && proc->requested_threads_started < proc->max_threads && (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */ /*spawn a new thread if we leave this out */) { /* 没有可用的binder线程,且之前已经进入到BINDER_LOOPER_STATE_REGISTERED * 或者BINDER_LOOPER_STATE_ENTERED状态启动一个新的binder线程 */ proc->requested_threads++; binder_debug(BINDER_DEBUG_THREADS, "%d:%d BR_SPAWN_LOOPER\n", proc->pid, thread->pid); if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer)) return -EFAULT; binder_stat_br(proc, thread, BR_SPAWN_LOOPER); } return 0; }
https://www.jianshu.com/p/4be292a51388